1f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/*
2f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)******************************************************************************
3f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
4f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Copyright (C) 1998-2008, International Business Machines
5f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Corporation and others.  All Rights Reserved.
6f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
7f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)******************************************************************************
8f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
9f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* File uprntf_p.c
10f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
11f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)* Modification History:
12f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*
13f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   Date        Name        Description
14f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   11/23/98    stephen     Creation.
15f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   03/12/99    stephen     Modified for new C API.
16f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*   08/07/2003  george      Reunify printf implementations
17f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)******************************************************************************
18f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)*/
19f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
20f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/utypes.h"
21f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
22f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#if !UCONFIG_NO_FORMATTING
23f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
24f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "unicode/ustring.h"
25f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
26f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "uprintf.h"
27f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "ufmt_cmn.h"
28f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "cmemory.h"
29f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#include "putilimp.h"
30f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
31f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* ANSI style formatting */
32f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Use US-ASCII characters only for formatting */
33f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
34f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* % */
35f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_SIMPLE_PERCENT {ufmt_simple_percent, u_printf_simple_percent_handler}
36f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* s */
37f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_STRING         {ufmt_string, u_printf_string_handler}
38f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* c */
39f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_CHAR           {ufmt_char, u_printf_char_handler}
40f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* d, i */
41f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_INT            {ufmt_int, u_printf_integer_handler}
42f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* u */
43f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_UINT           {ufmt_int, u_printf_uinteger_handler}
44f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* o */
45f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_OCTAL          {ufmt_int, u_printf_octal_handler}
46f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* x, X */
47f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_HEX            {ufmt_int, u_printf_hex_handler}
48f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* f */
49f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_DOUBLE         {ufmt_double, u_printf_double_handler}
50f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* e, E */
51f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_SCIENTIFIC     {ufmt_double, u_printf_scientific_handler}
52f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* g, G */
53f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_SCIDBL         {ufmt_double, u_printf_scidbl_handler}
54f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* n */
55f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_COUNT          {ufmt_count, u_printf_count_handler}
56f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
57f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* non-ANSI extensions */
58f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Use US-ASCII characters only for formatting */
59f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
60f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* p */
61f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_POINTER        {ufmt_pointer, u_printf_pointer_handler}
62f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* V */
63f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_SPELLOUT       {ufmt_double, u_printf_spellout_handler}
64f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* P */
65f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_PERCENT        {ufmt_double, u_printf_percent_handler}
66f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* C  K is old format */
67f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_UCHAR          {ufmt_uchar, u_printf_uchar_handler}
68f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* S  U is old format */
69f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_USTRING        {ufmt_ustring, u_printf_ustring_handler}
70f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
71f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
72f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UFMT_EMPTY {ufmt_empty, NULL}
73f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
74f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/**
75f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * A u_printf handler function.
76f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * A u_printf handler is responsible for handling a single u_printf
77f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * format specification, for example 'd' or 's'.
78f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param stream The UFILE to which to write output.
79f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param info A pointer to a <TT>u_printf_spec_info</TT> struct containing
80f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * information on the format specification.
81f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @param args A pointer to the argument data
82f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * @return The number of Unicode characters written to <TT>stream</TT>.
83f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
84f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)typedef int32_t U_EXPORT2
85f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_handler(const u_printf_stream_handler  *handler,
86f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
87f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 void                           *context,
88f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 ULocaleBundle                  *formatBundle,
89f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 const u_printf_spec_info       *info,
90f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                 const ufmt_args                *args);
91f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
92f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)typedef struct u_printf_info {
93f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_type_info info;
94f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_printf_handler *handler;
95f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} u_printf_info;
96f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
97f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/**
98f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) * Struct encapsulating a single uprintf format specification.
99f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) */
100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)typedef struct u_printf_spec {
101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  u_printf_spec_info    fInfo;        /* Information on this spec */
102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  int32_t        fWidthPos;     /* Position of width in arg list */
103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  int32_t        fPrecisionPos;    /* Position of precision in arg list */
104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)  int32_t        fArgPos;    /* Position of data in arg list */
105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)} u_printf_spec;
106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UPRINTF_NUM_FMT_HANDLERS 108
108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* We do not use handlers for 0-0x1f */
110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UPRINTF_BASE_FMT_HANDLERS 0x20
111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* buffer size for formatting */
113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UPRINTF_BUFFER_SIZE 1024
114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define UPRINTF_SYMBOL_BUFFER_SIZE 8
115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar gNullStr[] = {0x28, 0x6E, 0x75, 0x6C, 0x6C, 0x29, 0}; /* "(null)" */
117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const UChar gSpaceStr[] = {0x20, 0}; /* " " */
118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Sets the sign of a format based on u_printf_spec_info */
120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* TODO: Is setting the prefix symbol to a positive sign a good idea in all locales? */
121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void
122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_set_sign(UNumberFormat        *format,
123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   const u_printf_spec_info     *info,
124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   UChar *prefixBuffer,
125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   int32_t *prefixBufLen,
126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   UErrorCode *status)
127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fShowSign) {
129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *prefixBufLen = unum_getTextAttribute(format,
130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                              UNUM_POSITIVE_PREFIX,
131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                              prefixBuffer,
132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                              *prefixBufLen,
133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                              status);
134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (info->fSpace) {
135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* Setting UNUM_PLUS_SIGN_SYMBOL affects the exponent too. */
136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* unum_setSymbol(format, UNUM_PLUS_SIGN_SYMBOL, gSpaceStr, 1, &status); */
137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            unum_setTextAttribute(format, UNUM_POSITIVE_PREFIX, gSpaceStr, 1, status);
138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else {
140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            UChar plusSymbol[UPRINTF_SYMBOL_BUFFER_SIZE];
141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            int32_t symbolLen;
142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            symbolLen = unum_getSymbol(format,
144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                UNUM_PLUS_SIGN_SYMBOL,
145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                plusSymbol,
146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                sizeof(plusSymbol)/sizeof(*plusSymbol),
147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                status);
148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            unum_setTextAttribute(format,
149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                UNUM_POSITIVE_PREFIX,
150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                plusSymbol,
151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                symbolLen,
152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                status);
153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *prefixBufLen = 0;
157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static void
161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_reset_sign(UNumberFormat        *format,
162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   const u_printf_spec_info     *info,
163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   UChar *prefixBuffer,
164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   int32_t *prefixBufLen,
165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                   UErrorCode *status)
166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fShowSign) {
168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setTextAttribute(format,
169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                              UNUM_POSITIVE_PREFIX,
170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                              prefixBuffer,
171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                              *prefixBufLen,
172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                              status);
173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* handle a '%' */
178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_simple_percent_handler(const u_printf_stream_handler  *handler,
180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                void                           *context,
181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                ULocaleBundle                  *formatBundle,
182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                const u_printf_spec_info       *info,
183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                                const ufmt_args                *args)
184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    static const UChar PERCENT[] = { UP_PERCENT };
186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* put a single '%' onto the output */
188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->write(context, PERCENT, 1);
189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* handle 's' */
192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_string_handler(const u_printf_stream_handler  *handler,
194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        void                           *context,
195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        ULocaleBundle                  *formatBundle,
196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        const u_printf_spec_info       *info,
197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        const ufmt_args                *args)
198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar *s;
200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar buffer[UFMT_DEFAULT_BUFFER_SIZE];
201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t len, written;
202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t argSize;
203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const char *arg = (const char*)(args[0].ptrValue);
204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* convert from the default codepage to Unicode */
206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (arg) {
207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        argSize = (int32_t)strlen(arg) + 1;
208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (argSize >= MAX_UCHAR_BUFFER_SIZE(buffer)) {
209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            s = ufmt_defaultCPToUnicode(arg, argSize,
210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    (UChar *)uprv_malloc(MAX_UCHAR_BUFFER_NEEDED(argSize)),
211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    MAX_UCHAR_BUFFER_NEEDED(argSize));
212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(s == NULL) {
213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return 0;
214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else {
217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            s = ufmt_defaultCPToUnicode(arg, argSize, buffer,
218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    sizeof(buffer)/sizeof(UChar));
219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        s = (UChar *)gNullStr;
223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    len = u_strlen(s);
225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* width = minimum # of characters to write */
227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* precision = maximum # of characters to write */
228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fPrecision != -1 && info->fPrecision < len) {
229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        len = info->fPrecision;
230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    written = handler->pad_and_justify(context, info, s, len);
233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* clean up */
235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (gNullStr != s && buffer != s) {
236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(s);
237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return written;
240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_char_handler(const u_printf_stream_handler  *handler,
244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                      void                           *context,
245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                      ULocaleBundle                  *formatBundle,
246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                      const u_printf_spec_info       *info,
247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                      const ufmt_args                *args)
248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar s[UTF_MAX_CHAR_LENGTH+1];
250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t len = 1, written;
251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unsigned char arg = (unsigned char)(args[0].int64Value);
252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* convert from default codepage to Unicode */
254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_defaultCPToUnicode((const char *)&arg, 2, s, sizeof(s)/sizeof(UChar));
255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* Remember that this may be an MBCS character */
257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (arg != 0) {
258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        len = u_strlen(s);
259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* width = minimum # of characters to write */
262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* precision = maximum # of characters to write */
263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* precision is ignored when handling a char */
264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    written = handler->pad_and_justify(context, info, s, len);
266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return written;
268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_double_handler(const u_printf_stream_handler  *handler,
272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        void                           *context,
273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        ULocaleBundle                  *formatBundle,
274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        const u_printf_spec_info       *info,
275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        const ufmt_args                *args)
276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    double        num         = (double) (args[0].doubleValue);
278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UNumberFormat  *format;
279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar          result[UPRINTF_BUFFER_SIZE];
280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar          prefixBuffer[UPRINTF_BUFFER_SIZE];
281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t        prefixBufferLen = sizeof(prefixBuffer);
282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t        minDecimalDigits;
283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t        maxDecimalDigits;
284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t        resultLen;
285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode     status        = U_ZERO_ERROR;
286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prefixBuffer[0] = 0;
288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* mask off any necessary bits */
290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*  if(! info->fIsLongDouble)
291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    num &= DBL_MAX;*/
292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get the formatter */
294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* handle error */
297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(format == 0)
298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* save the formatter's state */
301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the appropriate flags and number of decimal digits on the formatter */
305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fPrecision != -1) {
306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* set the # of decimal digits */
307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if(info->fAlt) {
310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* '#' means always show decimal point */
311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* copy of printf behavior on Solaris - '#' shows 6 digits */
312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* # of decimal digits is 6 if precision not specified regardless of locale */
316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set whether to show the sign */
320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number */
325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        resultLen = 0;
329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* restore the number format */
332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* TODO: Is this needed? */
333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Reset back to original value regardless of what the error was */
338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode localStatus = U_ZERO_ERROR;
339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, resultLen);
343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* HSYS */
346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_integer_handler(const u_printf_stream_handler  *handler,
348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         void                           *context,
349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         ULocaleBundle                  *formatBundle,
350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const u_printf_spec_info       *info,
351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const ufmt_args                *args)
352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int64_t         num        = args[0].int64Value;
354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UNumberFormat   *format;
355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         prefixBufferLen = sizeof(prefixBuffer);
358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         minDigits     = -1;
359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         resultLen;
360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode      status        = U_ZERO_ERROR;
361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prefixBuffer[0] = 0;
363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* mask off any necessary bits */
365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fIsShort)
366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num = (int16_t)num;
367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if (!info->fIsLongLong)
368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num = (int32_t)num;
369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get the formatter */
371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* handle error */
374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(format == 0)
375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the appropriate flags on the formatter */
378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the minimum integer digits */
380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fPrecision != -1) {
381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* set the minimum # of digits */
382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        minDigits = unum_getAttribute(format, UNUM_MIN_INTEGER_DIGITS);
383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, info->fPrecision);
384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set whether to show the sign */
387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fShowSign) {
388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number */
392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    resultLen = unum_formatInt64(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        resultLen = 0;
396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* restore the number format */
399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (minDigits != -1) {
400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, minDigits);
401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Reset back to original value regardless of what the error was */
405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode localStatus = U_ZERO_ERROR;
406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, resultLen);
410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_hex_handler(const u_printf_stream_handler  *handler,
414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     void                           *context,
415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     ULocaleBundle                  *formatBundle,
416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     const u_printf_spec_info       *info,
417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                     const ufmt_args                *args)
418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int64_t         num        = args[0].int64Value;
420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         len        = UPRINTF_BUFFER_SIZE;
422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* mask off any necessary bits */
425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fIsShort)
426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num &= UINT16_MAX;
427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if (!info->fIsLongLong)
428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num &= UINT32_MAX;
429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number, preserving the minimum # of digits */
431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_64tou(result, &len, num, 16,
432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (UBool)(info->fSpec == 0x0078),
433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        (info->fPrecision == -1 && info->fZero) ? info->fWidth : info->fPrecision);
434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* convert to alt form, if desired */
436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(num != 0 && info->fAlt && len < UPRINTF_BUFFER_SIZE - 2) {
437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* shift the formatted string right by 2 chars */
438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        memmove(result + 2, result, len * sizeof(UChar));
439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result[0] = 0x0030;
440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result[1] = info->fSpec;
441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        len += 2;
442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, len);
445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_octal_handler(const u_printf_stream_handler  *handler,
449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       void                           *context,
450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       ULocaleBundle                  *formatBundle,
451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       const u_printf_spec_info       *info,
452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       const ufmt_args                *args)
453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int64_t         num        = args[0].int64Value;
455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         len        = UPRINTF_BUFFER_SIZE;
457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* mask off any necessary bits */
460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fIsShort)
461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num &= UINT16_MAX;
462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if (!info->fIsLongLong)
463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num &= UINT32_MAX;
464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number, preserving the minimum # of digits */
466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_64tou(result, &len, num, 8,
467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        FALSE, /* doesn't matter for octal */
468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        info->fPrecision == -1 && info->fZero ? info->fWidth : info->fPrecision);
469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* convert to alt form, if desired */
471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fAlt && result[0] != 0x0030 && len < UPRINTF_BUFFER_SIZE - 1) {
472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* shift the formatted string right by 1 char */
473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        memmove(result + 1, result, len * sizeof(UChar));
474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        result[0] = 0x0030;
475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        len += 1;
476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, len);
479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_uinteger_handler(const u_printf_stream_handler *handler,
483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          void                          *context,
484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          ULocaleBundle                 *formatBundle,
485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          const u_printf_spec_info      *info,
486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          const ufmt_args               *args)
487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int64_t         num        = args[0].int64Value;
489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UNumberFormat   *format;
490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         minDigits     = -1;
492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         resultLen;
493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode      status        = U_ZERO_ERROR;
494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* TODO: Fix this once uint64_t can be formatted. */
496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fIsShort)
497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num &= UINT16_MAX;
498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if (!info->fIsLongLong)
499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        num &= UINT32_MAX;
500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get the formatter */
502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* handle error */
505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(format == 0)
506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the appropriate flags on the formatter */
509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the minimum integer digits */
511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fPrecision != -1) {
512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* set the minimum # of digits */
513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        minDigits = unum_getAttribute(format, UNUM_MIN_INTEGER_DIGITS);
514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, info->fPrecision);
515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* To mirror other stdio implementations, we ignore the sign argument */
518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number */
520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    resultLen = unum_formatInt64(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        resultLen = 0;
524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* restore the number format */
527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (minDigits != -1) {
528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_MIN_INTEGER_DIGITS, minDigits);
529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, resultLen);
532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_pointer_handler(const u_printf_stream_handler  *handler,
536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         void                           *context,
537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         ULocaleBundle                  *formatBundle,
538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const u_printf_spec_info       *info,
539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const ufmt_args                *args)
540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         len  = UPRINTF_BUFFER_SIZE;
543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the pointer in hex */
545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_ptou(result, &len, args[0].ptrValue, TRUE/*, info->fPrecision*/);
546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, len);
548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_scientific_handler(const u_printf_stream_handler  *handler,
552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            void                           *context,
553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            ULocaleBundle                  *formatBundle,
554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            const u_printf_spec_info       *info,
555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                            const ufmt_args                *args)
556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    double          num         = (double) (args[0].doubleValue);
558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UNumberFormat   *format;
559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         prefixBufferLen = sizeof(prefixBuffer);
562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         minDecimalDigits;
563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         maxDecimalDigits;
564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode      status        = U_ZERO_ERROR;
565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar srcExpBuf[UPRINTF_SYMBOL_BUFFER_SIZE];
566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t srcLen, expLen;
567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t resultLen;
568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar expBuf[UPRINTF_SYMBOL_BUFFER_SIZE];
569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prefixBuffer[0] = 0;
571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* mask off any necessary bits */
573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*  if(! info->fIsLongDouble)
574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    num &= DBL_MAX;*/
575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get the formatter */
577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    format = u_locbund_getNumberFormat(formatBundle, UNUM_SCIENTIFIC);
578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* handle error */
580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(format == 0)
581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the appropriate flags on the formatter */
584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    srcLen = unum_getSymbol(format,
586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UNUM_EXPONENTIAL_SYMBOL,
587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcExpBuf,
588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        sizeof(srcExpBuf),
589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        &status);
590f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
591f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* Upper/lower case the e */
592f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fSpec == (UChar)0x65 /* e */) {
593f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        expLen = u_strToLower(expBuf, (int32_t)sizeof(expBuf),
594f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            srcExpBuf, srcLen,
595f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            formatBundle->fLocale,
596f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            &status);
597f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
598f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
599f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        expLen = u_strToUpper(expBuf, (int32_t)sizeof(expBuf),
600f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            srcExpBuf, srcLen,
601f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            formatBundle->fLocale,
602f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            &status);
603f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
604f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
605f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setSymbol(format,
606f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UNUM_EXPONENTIAL_SYMBOL,
607f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        expBuf,
608f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        expLen,
609f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        &status);
610f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
611f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* save the formatter's state */
612f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
613f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
614f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
615f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the appropriate flags and number of decimal digits on the formatter */
616f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fPrecision != -1) {
617f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* set the # of decimal digits */
618f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (info->fOrigSpec == (UChar)0x65 /* e */ || info->fOrigSpec == (UChar)0x45 /* E */) {
619f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
620f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
621f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else {
622f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, 1);
623f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, info->fPrecision);
624f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
625f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
626f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if(info->fAlt) {
627f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* '#' means always show decimal point */
628f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* copy of printf behavior on Solaris - '#' shows 6 digits */
629f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
630f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
631f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
632f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* # of decimal digits is 6 if precision not specified */
633f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
634f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
635f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
636f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set whether to show the sign */
637f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
638f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
639f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
640f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
641f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number */
642f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
643f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
644f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
645f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        resultLen = 0;
646f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
647f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
648f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* restore the number format */
649f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* TODO: Is this needed? */
650f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
651f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
652f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
653f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* Since we're the only one using the scientific
654f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)       format, we don't need to save the old exponent value. */
655f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*unum_setSymbol(format,
656f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UNUM_EXPONENTIAL_SYMBOL,
657f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcExpBuf,
658f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        srcLen,
659f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        &status);*/
660f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
661f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
662f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Reset back to original value regardless of what the error was */
663f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode localStatus = U_ZERO_ERROR;
664f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
665f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
666f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
667f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, resultLen);
668f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
669f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
670f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
671f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_percent_handler(const u_printf_stream_handler  *handler,
672f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         void                           *context,
673f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         ULocaleBundle                  *formatBundle,
674f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const u_printf_spec_info       *info,
675f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const ufmt_args                *args)
676f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
677f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    double          num         = (double) (args[0].doubleValue);
678f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UNumberFormat   *format;
679f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
680f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
681f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         prefixBufferLen = sizeof(prefixBuffer);
682f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         minDecimalDigits;
683f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         maxDecimalDigits;
684f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         resultLen;
685f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode      status        = U_ZERO_ERROR;
686f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
687f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prefixBuffer[0] = 0;
688f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
689f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* mask off any necessary bits */
690f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*  if(! info->fIsLongDouble)
691f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    num &= DBL_MAX;*/
692f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
693f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get the formatter */
694f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    format = u_locbund_getNumberFormat(formatBundle, UNUM_PERCENT);
695f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
696f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* handle error */
697f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(format == 0)
698f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
699f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
700f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* save the formatter's state */
701f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
702f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
703f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
704f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the appropriate flags and number of decimal digits on the formatter */
705f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fPrecision != -1) {
706f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* set the # of decimal digits */
707f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
708f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
709f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if(info->fAlt) {
710f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* '#' means always show decimal point */
711f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* copy of printf behavior on Solaris - '#' shows 6 digits */
712f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
713f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
714f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
715f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* # of decimal digits is 6 if precision not specified */
716f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
717f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
718f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
719f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set whether to show the sign */
720f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
721f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
722f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
723f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
724f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number */
725f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
726f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
727f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
728f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        resultLen = 0;
729f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
730f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
731f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* restore the number format */
732f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* TODO: Is this needed? */
733f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
734f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
735f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
736f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
737f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Reset back to original value regardless of what the error was */
738f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode localStatus = U_ZERO_ERROR;
739f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
740f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
741f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
742f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, resultLen);
743f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
744f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
745f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
746f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_ustring_handler(const u_printf_stream_handler  *handler,
747f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         void                           *context,
748f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         ULocaleBundle                  *formatBundle,
749f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const u_printf_spec_info       *info,
750f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                         const ufmt_args                *args)
751f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
752f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t len, written;
753f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *arg = (const UChar*)(args[0].ptrValue);
754f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
755f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* allocate enough space for the buffer */
756f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (arg == NULL) {
757f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        arg = gNullStr;
758f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
759f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    len = u_strlen(arg);
760f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
761f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* width = minimum # of characters to write */
762f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* precision = maximum # of characters to write */
763f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fPrecision != -1 && info->fPrecision < len) {
764f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        len = info->fPrecision;
765f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
766f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
767f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* determine if the string should be padded */
768f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    written = handler->pad_and_justify(context, info, arg, len);
769f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
770f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return written;
771f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
772f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
773f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
774f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_uchar_handler(const u_printf_stream_handler  *handler,
775f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       void                           *context,
776f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       ULocaleBundle                  *formatBundle,
777f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       const u_printf_spec_info       *info,
778f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       const ufmt_args                *args)
779f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
780f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t written = 0;
781f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar arg = (UChar)(args[0].int64Value);
782f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
783f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* width = minimum # of characters to write */
784f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* precision = maximum # of characters to write */
785f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* precision is ignored when handling a uchar */
786f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
787f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* determine if the string should be padded */
788f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    written = handler->pad_and_justify(context, info, &arg, 1);
789f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
790f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return written;
791f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
792f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
793f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
794f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_scidbl_handler(const u_printf_stream_handler  *handler,
795f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        void                           *context,
796f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        ULocaleBundle                  *formatBundle,
797f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        const u_printf_spec_info       *info,
798f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        const ufmt_args                *args)
799f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
800f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_printf_spec_info scidbl_info;
801f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    double      num = args[0].doubleValue;
802f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t     retVal;
803f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UNumberFormat *format;
804f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t maxSigDecimalDigits, significantDigits;
805f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
806f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    memcpy(&scidbl_info, info, sizeof(u_printf_spec_info));
807f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
808f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* determine whether to use 'd', 'e' or 'f' notation */
809f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (scidbl_info.fPrecision == -1 && num == uprv_trunc(num))
810f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    {
811f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* use 'f' notation */
812f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        scidbl_info.fSpec = 0x0066;
813f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        scidbl_info.fPrecision = 0;
814f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* call the double handler */
815f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        retVal = u_printf_double_handler(handler, context, formatBundle, &scidbl_info, args);
816f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
817f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if(num < 0.0001 || (scidbl_info.fPrecision < 1 && 1000000.0 <= num)
818f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        || (scidbl_info.fPrecision != -1 && num > uprv_pow10(scidbl_info.fPrecision)))
819f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    {
820f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* use 'e' or 'E' notation */
821f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        scidbl_info.fSpec = scidbl_info.fSpec - 2;
822f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (scidbl_info.fPrecision == -1) {
823f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            scidbl_info.fPrecision = 5;
824f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
825f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* call the scientific handler */
826f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        retVal = u_printf_scientific_handler(handler, context, formatBundle, &scidbl_info, args);
827f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
828f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
829f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        format = u_locbund_getNumberFormat(formatBundle, UNUM_DECIMAL);
830f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Check for null pointer */
831f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (format == NULL) {
832f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return 0;
833f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
834f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        maxSigDecimalDigits = unum_getAttribute(format, UNUM_MAX_SIGNIFICANT_DIGITS);
835f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        significantDigits = scidbl_info.fPrecision;
836f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
837f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* use 'f' notation */
838f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        scidbl_info.fSpec = 0x0066;
839f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (significantDigits == -1) {
840f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            significantDigits = 6;
841f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
842f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_SIGNIFICANT_DIGITS_USED, TRUE);
843f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_MAX_SIGNIFICANT_DIGITS, significantDigits);
844f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* call the double handler */
845f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        retVal = u_printf_double_handler(handler, context, formatBundle, &scidbl_info, args);
846f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_MAX_SIGNIFICANT_DIGITS, maxSigDecimalDigits);
847f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_SIGNIFICANT_DIGITS_USED, FALSE);
848f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
849f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return retVal;
850f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
851f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
852f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
853f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_count_handler(const u_printf_stream_handler  *handler,
854f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       void                           *context,
855f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       ULocaleBundle                  *formatBundle,
856f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       const u_printf_spec_info       *info,
857f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                       const ufmt_args                *args)
858f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
859f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t *count = (int32_t*)(args[0].ptrValue);
860f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
861f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* in the special case of count, the u_printf_spec_info's width */
862f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* will contain the # of chars written thus far */
863f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    *count = info->fWidth;
864f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
865f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return 0;
866f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
867f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
868f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static int32_t
869f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_spellout_handler(const u_printf_stream_handler *handler,
870f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          void                          *context,
871f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          ULocaleBundle                 *formatBundle,
872f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          const u_printf_spec_info      *info,
873f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                          const ufmt_args               *args)
874f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
875f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    double          num         = (double) (args[0].doubleValue);
876f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UNumberFormat   *format;
877f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           result[UPRINTF_BUFFER_SIZE];
878f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar           prefixBuffer[UPRINTF_BUFFER_SIZE];
879f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         prefixBufferLen = sizeof(prefixBuffer);
880f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         minDecimalDigits;
881f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         maxDecimalDigits;
882f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t         resultLen;
883f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode      status        = U_ZERO_ERROR;
884f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
885f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    prefixBuffer[0] = 0;
886f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
887f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* mask off any necessary bits */
888f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /*  if(! info->fIsLongDouble)
889f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    num &= DBL_MAX;*/
890f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
891f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get the formatter */
892f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    format = u_locbund_getNumberFormat(formatBundle, UNUM_SPELLOUT);
893f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
894f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* handle error */
895f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(format == 0)
896f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return 0;
897f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
898f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* save the formatter's state */
899f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    minDecimalDigits = unum_getAttribute(format, UNUM_MIN_FRACTION_DIGITS);
900f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    maxDecimalDigits = unum_getAttribute(format, UNUM_MAX_FRACTION_DIGITS);
901f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
902f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set the appropriate flags and number of decimal digits on the formatter */
903f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if(info->fPrecision != -1) {
904f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* set the # of decimal digits */
905f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, info->fPrecision);
906f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
907f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else if(info->fAlt) {
908f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* '#' means always show decimal point */
909f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* copy of printf behavior on Solaris - '#' shows 6 digits */
910f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
911f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
912f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    else {
913f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* # of decimal digits is 6 if precision not specified */
914f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        unum_setAttribute(format, UNUM_FRACTION_DIGITS, 6);
915f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
916f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
917f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* set whether to show the sign */
918f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
919f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_set_sign(format, info, prefixBuffer, &prefixBufferLen, &status);
920f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
921f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
922f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* format the number */
923f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    resultLen = unum_formatDouble(format, num, result, UPRINTF_BUFFER_SIZE, 0, &status);
924f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
925f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (U_FAILURE(status)) {
926f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        resultLen = 0;
927f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
928f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
929f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* restore the number format */
930f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* TODO: Is this needed? */
931f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MIN_FRACTION_DIGITS, minDecimalDigits);
932f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    unum_setAttribute(format, UNUM_MAX_FRACTION_DIGITS, maxDecimalDigits);
933f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
934f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (info->fShowSign) {
935f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Reset back to original value regardless of what the error was */
936f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        UErrorCode localStatus = U_ZERO_ERROR;
937f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        u_printf_reset_sign(format, info, prefixBuffer, &prefixBufferLen, &localStatus);
938f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
939f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
940f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return handler->pad_and_justify(context, info, result, resultLen);
941f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
942f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
943f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Use US-ASCII characters only for formatting. Most codepages have
944f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) characters 20-7F from Unicode. Using any other codepage specific
945f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) characters will make it very difficult to format the string on
946f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles) non-Unicode machines */
947f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static const u_printf_info g_u_printf_infos[UPRINTF_NUM_FMT_HANDLERS] = {
948f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 0x20 */
949f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
950f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_SIMPLE_PERCENT,UFMT_EMPTY,         UFMT_EMPTY,
951f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
952f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
953f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
954f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 0x30 */
955f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
956f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
957f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
958f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
959f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
960f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 0x40 */
961f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_UCHAR,
962f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_SCIENTIFIC,    UFMT_EMPTY,         UFMT_SCIDBL,
963f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#ifdef U_USE_OBSOLETE_IO_FORMATTING
964f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_UCHAR/*deprecated*/,
965f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#else
966f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
967f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
968f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
969f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
970f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 0x50 */
971f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_PERCENT,       UFMT_EMPTY,         UFMT_EMPTY,         UFMT_USTRING,
972f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#ifdef U_USE_OBSOLETE_IO_FORMATTING
973f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_USTRING/*deprecated*/,UFMT_SPELLOUT,      UFMT_EMPTY,
974f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#else
975f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_SPELLOUT,      UFMT_EMPTY,
976f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif
977f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_HEX,           UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
978f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
979f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
980f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 0x60 */
981f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_CHAR,
982f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_INT,           UFMT_SCIENTIFIC,    UFMT_DOUBLE,        UFMT_SCIDBL,
983f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_INT,           UFMT_EMPTY,         UFMT_EMPTY,
984f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_COUNT,         UFMT_OCTAL,
985f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
986f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* 0x70 */
987f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_POINTER,       UFMT_EMPTY,         UFMT_EMPTY,         UFMT_STRING,
988f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_UINT,          UFMT_EMPTY,         UFMT_EMPTY,
989f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_HEX,           UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
990f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,         UFMT_EMPTY,
991f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)};
992f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
993f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* flag characters for uprintf */
994f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define FLAG_MINUS 0x002D
995f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define FLAG_PLUS 0x002B
996f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define FLAG_SPACE 0x0020
997f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define FLAG_POUND 0x0023
998f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define FLAG_ZERO  0x0030
999f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define FLAG_PAREN 0x0028
1000f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1001f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define ISFLAG(s)    (s) == FLAG_MINUS || \
1002f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == FLAG_PLUS || \
1003f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == FLAG_SPACE || \
1004f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == FLAG_POUND || \
1005f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == FLAG_ZERO || \
1006f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == FLAG_PAREN
1007f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1008f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* special characters for uprintf */
1009f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define SPEC_ASTERISK 0x002A
1010f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define SPEC_DOLLARSIGN 0x0024
1011f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define SPEC_PERIOD 0x002E
1012f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define SPEC_PERCENT 0x0025
1013f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1014f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* unicode digits */
1015f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_ZERO 0x0030
1016f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_ONE 0x0031
1017f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_TWO 0x0032
1018f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_THREE 0x0033
1019f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_FOUR 0x0034
1020f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_FIVE 0x0035
1021f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_SIX 0x0036
1022f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_SEVEN 0x0037
1023f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_EIGHT 0x0038
1024f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define DIGIT_NINE 0x0039
1025f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1026f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define ISDIGIT(s)    (s) == DIGIT_ZERO || \
1027f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_ONE || \
1028f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_TWO || \
1029f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_THREE || \
1030f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_FOUR || \
1031f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_FIVE || \
1032f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_SIX || \
1033f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_SEVEN || \
1034f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_EIGHT || \
1035f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == DIGIT_NINE
1036f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1037f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* u_printf modifiers */
1038f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MOD_H 0x0068
1039f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MOD_LOWERL 0x006C
1040f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define MOD_L 0x004C
1041f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1042f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#define ISMOD(s)    (s) == MOD_H || \
1043f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == MOD_LOWERL || \
1044f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            (s) == MOD_L
1045f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* Returns an array of the parsed argument type given in the format string. */
1046f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)static ufmt_args* parseArguments(const UChar *alias, va_list ap, UErrorCode *status) {
1047f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_args *arglist = NULL;
1048f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_type_info *typelist = NULL;
1049f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UBool *islonglong = NULL;
1050f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t size = 0;
1051f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    int32_t pos = 0;
1052f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UChar type;
1053f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uint16_t handlerNum;
1054f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *aliasStart = alias;
1055f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1056f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* get maximum number of arguments */
1057f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(;;) {
1058f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* find % */
1059f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while(*alias != UP_PERCENT && *alias != 0x0000) {
1060f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            alias++;
1061f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1062f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1063f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*alias == 0x0000) {
1064f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1065f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1066f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1067f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        alias++;
1068f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1069f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* handle the pos number */
1070f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(ISDIGIT(*alias)) {
1071f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1072f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* handle positional parameters */
1073f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(ISDIGIT(*alias)) {
1074f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                pos = (int) (*alias++ - DIGIT_ZERO);
1075f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1076f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                while(ISDIGIT(*alias)) {
1077f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    pos *= 10;
1078f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    pos += (int) (*alias++ - DIGIT_ZERO);
1079f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1080f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1081f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1082f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* if there is no '$', don't read anything */
1083f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(*alias != SPEC_DOLLARSIGN) {
1084f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                return NULL;
1085f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1086f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
1087f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return NULL;
1088f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1089f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1090f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (pos > size) {
1091f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            size = pos;
1092f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1093f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1094f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1095f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* create the parsed argument list */
1096f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    typelist = (ufmt_type_info*)uprv_malloc(sizeof(ufmt_type_info) * size);
1097f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    islonglong = (UBool*)uprv_malloc(sizeof(UBool) * size);
1098f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    arglist = (ufmt_args*)uprv_malloc(sizeof(ufmt_args) * size);
1099f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1100f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* If malloc failed, return NULL */
1101f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!typelist || !islonglong || !arglist) {
1102f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (typelist) {
1103f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_free(typelist);
1104f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1105f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1106f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (islonglong) {
1107f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_free(islonglong);
1108f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1109f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1110f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (arglist) {
1111f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            uprv_free(arglist);
1112f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1113f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1114f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        *status = U_MEMORY_ALLOCATION_ERROR;
1115f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        return NULL;
1116f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1117f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1118f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* reset alias back to the beginning */
1119f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    alias = aliasStart;
1120f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1121f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for(;;) {
1122f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* find % */
1123f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while(*alias != UP_PERCENT && *alias != 0x0000) {
1124f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            alias++;
1125f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1126f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1127f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*alias == 0x0000) {
1128f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1129f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1130f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1131f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        alias++;
1132f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1133f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* handle positional parameters */
1134f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(ISDIGIT(*alias)) {
1135f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            pos = (int) (*alias++ - DIGIT_ZERO);
1136f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1137f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            while(ISDIGIT(*alias)) {
1138f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                pos *= 10;
1139f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                pos += (int) (*alias++ - DIGIT_ZERO);
1140f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1141f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1142f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* offset position by 1 */
1143f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        pos--;
1144f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1145f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* skip over everything except for the type */
1146f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while (ISMOD(*alias) || ISFLAG(*alias) || ISDIGIT(*alias) ||
1147f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *alias == SPEC_ASTERISK || *alias == SPEC_PERIOD || *alias == SPEC_DOLLARSIGN) {
1148f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                islonglong[pos] = FALSE;
1149f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if (ISMOD(*alias)) {
1150f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    alias++;
1151f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (*alias == MOD_LOWERL) {
1152f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        islonglong[pos] = TRUE;
1153f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1154f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1155f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                alias++;
1156f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1157f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        type = *alias;
1158f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1159f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* store the argument type in the correct position of the parsed argument list */
1160f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        handlerNum = (uint16_t)(type - UPRINTF_BASE_FMT_HANDLERS);
1161f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (handlerNum < UPRINTF_NUM_FMT_HANDLERS) {
1162f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typelist[pos] = g_u_printf_infos[ handlerNum ].info;
1163f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        } else {
1164f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            typelist[pos] = ufmt_empty;
1165f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1166f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1167f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1168f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* store argument in arglist */
1169f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    for (pos = 0; pos < size; pos++) {
1170f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        switch (typelist[pos]) {
1171f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_string:
1172f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_ustring:
1173f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_pointer:
1174f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            arglist[pos].ptrValue = va_arg(ap, void*);
1175f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1176f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_char:
1177f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_uchar:
1178f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_int:
1179f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (islonglong[pos]) {
1180f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                arglist[pos].int64Value = va_arg(ap, int64_t);
1181f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1182f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            else {
1183f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                arglist[pos].int64Value = va_arg(ap, int32_t);
1184f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1185f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1186f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_float:
1187f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            arglist[pos].floatValue = (float) va_arg(ap, double);
1188f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1189f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        case ufmt_double:
1190f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            arglist[pos].doubleValue = va_arg(ap, double);
1191f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1192f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        default:
1193f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* else args is ignored */
1194f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            arglist[pos].ptrValue = NULL;
1195f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1196f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1197f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1198f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1199f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_free(typelist);
1200f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uprv_free(islonglong);
1201f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1202f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return arglist;
1203f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1204f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1205f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)/* We parse the argument list in Unicode */
1206f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)U_CFUNC int32_t
1207f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)u_printf_parse(const u_printf_stream_handler *streamHandler,
1208f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)               const UChar     *fmt,
1209f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)               void            *context,
1210f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)               u_localized_print_string *locStringContext,
1211f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)               ULocaleBundle   *formatBundle,
1212f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)               int32_t         *written,
1213f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)               va_list         ap)
1214f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles){
1215f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    uint16_t         handlerNum;
1216f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_args        args;
1217f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_type_info   argType;
1218f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_printf_handler *handler;
1219f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_printf_spec    spec;
1220f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    u_printf_spec_info *info = &(spec.fInfo);
1221f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1222f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *alias = fmt;
1223f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *backup;
1224f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *lastAlias;
1225f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    const UChar *orgAlias = fmt;
1226f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* parsed argument list */
1227f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    ufmt_args *arglist = NULL; /* initialized it to avoid compiler warnings */
1228f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    UErrorCode status = U_ZERO_ERROR;
1229f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (!locStringContext || locStringContext->available >= 0) {
1230f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* get the parsed list of argument types */
1231f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        arglist = parseArguments(orgAlias, ap, &status);
1232f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1233f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Return error if parsing failed. */
1234f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (U_FAILURE(status)) {
1235f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            return -1;
1236f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1237f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1238f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1239f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* iterate through the pattern */
1240f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    while(!locStringContext || locStringContext->available >= 0) {
1241f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1242f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* find the next '%' */
1243f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        lastAlias = alias;
1244f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while(*alias != UP_PERCENT && *alias != 0x0000) {
1245f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            alias++;
1246f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1247f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1248f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* write any characters before the '%' */
1249f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(alias > lastAlias) {
1250f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *written += (streamHandler->write)(context, lastAlias, (int32_t)(alias - lastAlias));
1251f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1252f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1253f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* break if at end of string */
1254f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*alias == 0x0000) {
1255f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            break;
1256f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1257f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1258f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* initialize spec to default values */
1259f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        spec.fWidthPos     = -1;
1260f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        spec.fPrecisionPos = -1;
1261f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        spec.fArgPos       = -1;
1262f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1263f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_memset(info, 0, sizeof(*info));
1264f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        info->fPrecision    = -1;
1265f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        info->fWidth        = -1;
1266f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        info->fPadChar      = 0x0020;
1267f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1268f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* skip over the initial '%' */
1269f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        alias++;
1270f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1271f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Check for positional argument */
1272f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(ISDIGIT(*alias)) {
1273f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1274f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* Save the current position */
1275f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            backup = alias;
1276f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1277f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* handle positional parameters */
1278f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(ISDIGIT(*alias)) {
1279f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                spec.fArgPos = (int) (*alias++ - DIGIT_ZERO);
1280f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1281f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                while(ISDIGIT(*alias)) {
1282f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    spec.fArgPos *= 10;
1283f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    spec.fArgPos += (int) (*alias++ - DIGIT_ZERO);
1284f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1285f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1286f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1287f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* if there is no '$', don't read anything */
1288f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(*alias != SPEC_DOLLARSIGN) {
1289f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                spec.fArgPos = -1;
1290f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                alias = backup;
1291f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1292f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* munge the '$' */
1293f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            else
1294f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                alias++;
1295f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1296f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1297f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Get any format flags */
1298f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        while(ISFLAG(*alias)) {
1299f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            switch(*alias++) {
1300f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1301f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* left justify */
1302f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case FLAG_MINUS:
1303f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fLeft = TRUE;
1304f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1305f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1306f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* always show sign */
1307f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case FLAG_PLUS:
1308f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fShowSign = TRUE;
1309f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1310f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1311f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* use space if no sign present */
1312f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case FLAG_SPACE:
1313f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fShowSign = TRUE;
1314f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fSpace = TRUE;
1315f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1316f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1317f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* use alternate form */
1318f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case FLAG_POUND:
1319f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fAlt = TRUE;
1320f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1321f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1322f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* pad with leading zeroes */
1323f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case FLAG_ZERO:
1324f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fZero = TRUE;
1325f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPadChar = 0x0030;
1326f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1327f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1328f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* pad character specified */
1329f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case FLAG_PAREN:
1330f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1331f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* TODO test that all four are numbers */
1332f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* first four characters are hex values for pad char */
1333f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPadChar = (UChar)ufmt_digitvalue(*alias++);
1334f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*alias++));
1335f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*alias++));
1336f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPadChar = (UChar)((info->fPadChar * 16) + ufmt_digitvalue(*alias++));
1337f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1338f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* final character is ignored */
1339f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                alias++;
1340f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1341f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1342f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1343f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1344f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1345f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Get the width */
1346f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1347f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* width is specified out of line */
1348f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*alias == SPEC_ASTERISK) {
1349f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1350f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            info->fWidth = -2;
1351f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1352f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* Skip the '*' */
1353f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            alias++;
1354f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1355f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* Save the current position */
1356f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            backup = alias;
1357f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1358f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* handle positional parameters */
1359f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(ISDIGIT(*alias)) {
1360f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                spec.fWidthPos = (int) (*alias++ - DIGIT_ZERO);
1361f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1362f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                while(ISDIGIT(*alias)) {
1363f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    spec.fWidthPos *= 10;
1364f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    spec.fWidthPos += (int) (*alias++ - DIGIT_ZERO);
1365f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1366f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1367f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1368f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* if there is no '$', don't read anything */
1369f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(*alias != SPEC_DOLLARSIGN) {
1370f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                spec.fWidthPos = -1;
1371f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                alias = backup;
1372f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1373f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* munge the '$' */
1374f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            else
1375f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                alias++;
1376f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1377f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* read the width, if present */
1378f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else if(ISDIGIT(*alias)){
1379f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            info->fWidth = (int) (*alias++ - DIGIT_ZERO);
1380f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1381f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            while(ISDIGIT(*alias)) {
1382f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fWidth *= 10;
1383f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fWidth += (int) (*alias++ - DIGIT_ZERO);
1384f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1385f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1386f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1387f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Get the precision */
1388f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1389f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(*alias == SPEC_PERIOD) {
1390f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1391f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* eat up the '.' */
1392f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            alias++;
1393f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1394f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* precision is specified out of line */
1395f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(*alias == SPEC_ASTERISK) {
1396f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1397f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPrecision = -2;
1398f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1399f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* Skip the '*' */
1400f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                alias++;
1401f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1402f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* save the current position */
1403f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                backup = alias;
1404f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1405f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* handle positional parameters */
1406f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(ISDIGIT(*alias)) {
1407f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    spec.fPrecisionPos = (int) (*alias++ - DIGIT_ZERO);
1408f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1409f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    while(ISDIGIT(*alias)) {
1410f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        spec.fPrecisionPos *= 10;
1411f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        spec.fPrecisionPos += (int) (*alias++ - DIGIT_ZERO);
1412f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1413f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1414f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* if there is no '$', don't read anything */
1415f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if(*alias != SPEC_DOLLARSIGN) {
1416f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        spec.fPrecisionPos = -1;
1417f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        alias = backup;
1418f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1419f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    else {
1420f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        /* munge the '$' */
1421f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        alias++;
1422f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1423f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1424f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1425f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* read the precision */
1426f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            else if(ISDIGIT(*alias)){
1427f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPrecision = (int) (*alias++ - DIGIT_ZERO);
1428f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1429f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                while(ISDIGIT(*alias)) {
1430f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    info->fPrecision *= 10;
1431f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    info->fPrecision += (int) (*alias++ - DIGIT_ZERO);
1432f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1433f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1434f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1435f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1436f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* Get any modifiers */
1437f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(ISMOD(*alias)) {
1438f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            switch(*alias++) {
1439f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1440f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* short */
1441f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case MOD_H:
1442f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fIsShort = TRUE;
1443f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1444f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1445f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* long or long long */
1446f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case MOD_LOWERL:
1447f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                if(*alias == MOD_LOWERL) {
1448f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    info->fIsLongLong = TRUE;
1449f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* skip over the next 'l' */
1450f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    alias++;
1451f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1452f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                else
1453f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    info->fIsLong = TRUE;
1454f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1455f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1456f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* long double */
1457f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            case MOD_L:
1458f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fIsLongDouble = TRUE;
1459f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                break;
1460f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1461f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1462f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1463f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* finally, get the specifier letter */
1464f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        info->fSpec = *alias++;
1465f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        info->fOrigSpec = info->fSpec;
1466f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1467f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* fill in the precision and width, if specified out of line */
1468f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1469f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* width specified out of line */
1470f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(spec.fInfo.fWidth == -2) {
1471f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(spec.fWidthPos == -1) {
1472f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* read the width from the argument list */
1473f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fWidth = va_arg(ap, int32_t);
1474f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1475f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* else handle positional parameter */
1476f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1477f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* if it's negative, take the absolute value and set left alignment */
1478f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(info->fWidth < 0) {
1479f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fWidth *= -1; /* Make positive */
1480f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fLeft = TRUE;
1481f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1482f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1483f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1484f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        /* precision specified out of line */
1485f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if(info->fPrecision == -2) {
1486f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(spec.fPrecisionPos == -1) {
1487f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* read the precision from the argument list */
1488f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPrecision = va_arg(ap, int32_t);
1489f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1490f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* else handle positional parameter */
1491f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1492f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* if it's negative, set it to zero */
1493f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(info->fPrecision < 0)
1494f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                info->fPrecision = 0;
1495f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1496f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1497f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        handlerNum = (uint16_t)(info->fSpec - UPRINTF_BASE_FMT_HANDLERS);
1498f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        if (handlerNum < UPRINTF_NUM_FMT_HANDLERS) {
1499f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* query the info function for argument information */
1500f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            argType = g_u_printf_infos[ handlerNum ].info;
1501f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1502f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* goto the correct argument on arg_list if position is specified */
1503f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if (spec.fArgPos > 0) {
1504f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* offset position by 1 */
1505f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                spec.fArgPos--;
1506f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                switch(argType) {
1507f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_count:
1508f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* set the spec's width to the # of chars written */
1509f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    info->fWidth = *written;
1510f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* fall through to set the pointer */
1511f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_string:
1512f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_ustring:
1513f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_pointer:
1514f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.ptrValue = arglist[spec.fArgPos].ptrValue;
1515f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1516f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_char:
1517f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_uchar:
1518f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_int:
1519f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.int64Value = arglist[spec.fArgPos].int64Value;
1520f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1521f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_float:
1522f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.floatValue = arglist[spec.fArgPos].floatValue;
1523f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1524f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_double:
1525f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.doubleValue = arglist[spec.fArgPos].doubleValue;
1526f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1527f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                default:
1528f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* else args is ignored */
1529f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.ptrValue = NULL;
1530f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1531f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1532f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            } else { /* no positional argument specified */
1533f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                switch(argType) {
1534f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_count:
1535f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* set the spec's width to the # of chars written */
1536f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    info->fWidth = *written;
1537f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* fall through to set the pointer */
1538f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_string:
1539f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_ustring:
1540f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_pointer:
1541f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.ptrValue = va_arg(ap, void*);
1542f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1543f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_char:
1544f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_uchar:
1545f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_int:
1546f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    if (info->fIsLongLong) {
1547f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        args.int64Value = va_arg(ap, int64_t);
1548f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1549f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    else {
1550f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                        args.int64Value = va_arg(ap, int32_t);
1551f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    }
1552f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1553f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_float:
1554f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.floatValue = (float) va_arg(ap, double);
1555f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1556f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                case ufmt_double:
1557f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.doubleValue = va_arg(ap, double);
1558f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1559f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                default:
1560f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    /* else args is ignored */
1561f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    args.ptrValue = NULL;
1562f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                    break;
1563f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                }
1564f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1565f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1566f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* call the handler function */
1567f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            handler = g_u_printf_infos[ handlerNum ].handler;
1568f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            if(handler != 0) {
1569f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *written += (*handler)(streamHandler, context, formatBundle, info, &args);
1570f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1571f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            else {
1572f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                /* just echo unknown tags */
1573f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)                *written += (streamHandler->write)(context, fmt, (int32_t)(alias - lastAlias));
1574f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            }
1575f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1576f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        else {
1577f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            /* just echo unknown tags */
1578f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)            *written += (streamHandler->write)(context, fmt, (int32_t)(alias - lastAlias));
1579f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        }
1580f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1581f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* delete parsed argument list */
1582f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    if (arglist != NULL) {
1583f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)        uprv_free(arglist);
1584f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    }
1585f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    /* return # of characters in this format that have been parsed. */
1586f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)    return (int32_t)(alias - fmt);
1587f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)}
1588f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)
1589f4ed1cf5d184064c4cf0e4359c6d5d8aadb50afaTorne (Richard Coles)#endif /* #if !UCONFIG_NO_FORMATTING */
1590