1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16
17/* [Standardize-exceptions] Use unsafe function: Portability
18 * [reason] Use unsafe function to implement security function to maintain platform compatibility.
19 *          And sufficient input validation is performed before calling
20 */
21
22#ifndef OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
23#define OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5
24
25#define SECUREC_FLOAT_BUFSIZE (309+40)  /* max float point value */
26#define SECUREC_FLOAT_BUFSIZE_LB (4932+40)  /* max long double value */
27
28#define SECUREC_INT_MAX       2147483647
29
30#define SECUREC_MUL10(x) ((((x) << 2) + (x)) << 1)
31#define SECUREC_INT_MAX_DIV_TEN       21474836
32#define SECUREC_MUL10_ADD_BEYOND_MAX(val) (((val) > SECUREC_INT_MAX_DIV_TEN))
33
34#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K
35#define SECUREC_FMT_STR_LEN (8)
36#else
37#define SECUREC_FMT_STR_LEN (16)
38#endif
39
40typedef struct {
41    unsigned int flags;
42    int fldWidth;
43    int precision;
44    int bufferIsWide;           /* flag for buffer contains wide chars */
45    int dynWidth;               /* %*   1 width from variable parameter ;0 not */
46    int dynPrecision;           /* %.*  1 precision from variable parameter ;0 not */
47} SecFormatAttr;
48
49typedef union {
50    char *str;                  /* not a null terminated  string */
51    wchar_t *wStr;
52} SecFormatBuf;
53
54typedef union {
55    char str[SECUREC_BUFFER_SIZE + 1];
56#ifdef SECUREC_FOR_WCHAR
57    wchar_t wStr[SECUREC_BUFFER_SIZE + 1];
58#endif
59} SecBuffer;
60
61static int SecIndirectSprintf(char *strDest, const char *format, ...)
62{
63    int ret;                    /* If initialization causes  e838 */
64    va_list arglist;
65
66    va_start(arglist, format);
67    SECUREC_MASK_MSVC_CRT_WARNING
68    ret = vsprintf(strDest, format, arglist);
69    SECUREC_END_MASK_MSVC_CRT_WARNING
70    va_end(arglist);
71    (void)arglist;              /* to clear e438 last value assigned not used , the compiler will optimize this code */
72
73    return ret;
74}
75
76#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
77/* to clear e506 warning */
78static int SecIsSameSize(size_t sizeA, size_t sizeB)
79{
80    return sizeA == sizeB;
81}
82#endif
83
84#define SECUREC_SPECIAL(_val, Base) \
85            case Base: \
86            do { \
87                *--formatBuf.str = digits[_val % Base]; \
88            }while ((_val /= Base) != 0)
89
90#define SECUREC_SAFE_WRITE_PREFIX(src, txtLen, _stream, outChars) do { \
91            for (ii = 0; ii < txtLen; ++ii) { \
92                *((SecChar *)(void *)(_stream->cur)) = *(src); \
93                _stream->cur += sizeof(SecChar);              \
94                ++(src);                                      \
95            } \
96            _stream->count -= txtLen * (int)(sizeof(SecChar)); \
97            *(outChars) = *(outChars) + (txtLen); \
98        } SECUREC_WHILE_ZERO
99
100#define SECUREC_SAFE_WRITE_STR(src, txtLen, _stream, outChars) do { \
101            if (txtLen < 12 /* for mobile number length */) { \
102                for (ii = 0; ii < txtLen; ++ii) { \
103                    *((SecChar *)(void *)(_stream->cur)) = *(src); \
104                    _stream->cur += sizeof(SecChar); \
105                    ++(src); \
106                } \
107            } else { \
108                (void)memcpy(_stream->cur, src, ((size_t)(unsigned int)txtLen * (sizeof(SecChar)))); \
109                _stream->cur += (size_t)(unsigned int)txtLen * (sizeof(SecChar)); \
110            } \
111            _stream->count -= txtLen * (int)(sizeof(SecChar)); \
112            *(outChars) = *(outChars) + (txtLen); \
113        } SECUREC_WHILE_ZERO
114
115#define SECUREC_SAFE_WRITE_CHAR(_ch, _stream, outChars) do { \
116            *((SecChar *)(void *)(_stream->cur)) = (SecChar)_ch; \
117            _stream->cur += sizeof(SecChar); \
118            _stream->count -= (int)(sizeof(SecChar)); \
119            *(outChars) = *(outChars) + 1; \
120        } SECUREC_WHILE_ZERO
121
122#define SECUREC_SAFE_PADDING(padChar, padLen, _stream, outChars) do { \
123            for (ii = 0; ii < padLen; ++ii) { \
124                *((SecChar *)(void *)(_stream->cur)) = (SecChar)padChar; \
125                _stream->cur += sizeof(SecChar); \
126            } \
127            _stream->count -= padLen * (int)(sizeof(SecChar)); \
128            *(outChars) = *(outChars) + (padLen); \
129        } SECUREC_WHILE_ZERO
130
131/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */
132#define SECUREC_IS_REST_BUF_ENOUGH(needLen) ((int)(stream->count - (int)needLen * (int)(sizeof(SecChar)))  >= 0)
133
134#define SECUREC_FMT_STATE_OFFSET  256
135#ifdef SECUREC_FOR_WCHAR
136#define SECUREC_FMT_TYPE(c, fmtTable)  ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \
137                                      (fmtTable[(unsigned char)(c)]) : 0)
138#define SECUREC_DECODE_STATE(c, fmtTable, laststate) (SecFmtState)(((fmtTable[(SECUREC_FMT_TYPE(c,fmtTable)) * \
139                                                                            ((unsigned char)STAT_INVALID + 1) + \
140                                                                            (unsigned char)(laststate) + \
141                                                                            SECUREC_FMT_STATE_OFFSET])))
142#else
143#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)((fmtTable[(fmtTable[(unsigned char)(c)]) * \
144                                                                           ((unsigned char)STAT_INVALID + 1) + \
145                                                                           (unsigned char)(laststate) + \
146                                                                           SECUREC_FMT_STATE_OFFSET]))
147#endif
148
149#define PUBLIC_FLAG_LEN  8
150#define PRIVATE_FLAG_LEN 9
151#define PUBLIC_FLAG      "{public}"
152#define PRIVATE_FLAG     "{private}"
153
154static void SecWritePrivateStr(SecPrintfStream *stream, int *pCharsOut)
155{
156    int ii = 0;
157#define PRIVATE_STR_LEN (9)
158#ifndef SECUREC_FOR_WCHAR
159    static const char PRIVACY_STRING[] = "<private>";
160    const char *pPrivStr = PRIVACY_STRING;
161
162    if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) {
163        SECUREC_SAFE_WRITE_STR(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
164    } else {
165        SECUREC_WRITE_STRING(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
166    }
167#else
168    static const wchar_t wprivacyString[] = { L'<', L'p', L'r', L'i', L'v', L'a', L't', L'e', L'>', L'\0' };
169    const wchar_t *pwPrivStr = wprivacyString;
170
171    if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) {
172        SECUREC_SAFE_WRITE_STR(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
173    } else {
174        SECUREC_WRITE_STRING(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut);
175    }
176#endif
177}
178
179static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr)
180{
181    switch (ch) {
182    case SECUREC_CHAR(' '):
183        attr->flags |= SECUREC_FLAG_SIGN_SPACE;
184        break;
185    case SECUREC_CHAR('+'):
186        attr->flags |= SECUREC_FLAG_SIGN;
187        break;
188    case SECUREC_CHAR('-'):
189        attr->flags |= SECUREC_FLAG_LEFT;
190        break;
191    case SECUREC_CHAR('0'):
192        attr->flags |= SECUREC_FLAG_LEADZERO;   /* add zero th the front */
193        break;
194    case SECUREC_CHAR('#'):
195        attr->flags |= SECUREC_FLAG_ALTERNATE;  /* output %x with 0x */
196        break;
197    default:
198        break;
199    }
200    return;
201}
202
203static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format)
204{
205    switch (ch) {
206#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
207    case SECUREC_CHAR('j'):
208        attr->flags |= SECUREC_FLAG_INTMAX;
209        break;
210#endif
211    case SECUREC_CHAR('q'):  /* fall-through */ /* FALLTHRU */
212    case SECUREC_CHAR('L'):
213        attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE;
214        break;
215    case SECUREC_CHAR('l'):
216        if (**format == SECUREC_CHAR('l')) {
217            ++(*format);
218            attr->flags |= SECUREC_FLAG_LONGLONG;   /* long long */
219        } else {
220            attr->flags |= SECUREC_FLAG_LONG;   /* long int or wchar_t */
221        }
222        break;
223    case SECUREC_CHAR('t'):
224        attr->flags |= SECUREC_FLAG_PTRDIFF;
225        break;
226#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
227    case SECUREC_CHAR('z'):
228        attr->flags |= SECUREC_FLAG_SIZE;
229        break;
230    case SECUREC_CHAR('Z'):
231        attr->flags |= SECUREC_FLAG_SIZE;
232        break;
233#endif
234
235    case SECUREC_CHAR('I'):
236#ifdef SECUREC_ON_64BITS
237        attr->flags |= SECUREC_FLAG_I64;    /* %I  to  INT64 */
238#endif
239        if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) {
240            (*format) += 2;
241            attr->flags |= SECUREC_FLAG_I64;    /* %I64  to  INT64 */
242        } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) {
243            (*format) += 2;
244            attr->flags &= ~SECUREC_FLAG_I64;   /* %I64  to  INT32 */
245        } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) ||
246                   (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) ||
247                   (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) {
248            /* do nothing */
249        } else {
250            /* Compatibility  code for "%I" just print I */
251            return -1;
252        }
253        break;
254
255    case SECUREC_CHAR('h'):
256        if (**format == SECUREC_CHAR('h')) {
257            attr->flags |= SECUREC_FLAG_CHAR;   /* char */
258        } else {
259            attr->flags |= SECUREC_FLAG_SHORT;  /* short int */
260        }
261        break;
262
263    case SECUREC_CHAR('w'):
264        attr->flags |= SECUREC_FLAG_WIDECHAR;   /* wide char */
265        break;
266    default:
267        break;
268
269    }
270
271    return 0;
272}
273
274static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer)
275{
276    int textLen;
277    wchar_t wchar;
278
279#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS))
280    attr->flags &= ~SECUREC_FLAG_LEADZERO;
281#endif
282
283#ifdef SECUREC_FOR_WCHAR
284    attr->bufferIsWide = 1;
285    wchar = (wchar_t)cValue;
286    if (attr->flags & SECUREC_FLAG_SHORT) {
287        /* multibyte character to wide  character */
288        char tempchar[2];
289        tempchar[0] = (char)(wchar & 0x00ff);
290        tempchar[1] = '\0';
291
292        if (mbtowc(buffer->wStr, tempchar, sizeof(tempchar)) < 0) {
293            return -1;
294        }
295    } else {
296        buffer->wStr[0] = wchar;
297    }
298    formatBuf->wStr = buffer->wStr;
299    textLen = 1;                /* only 1 wide character */
300#else
301    attr->bufferIsWide = 0;
302    if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
303        wchar = (wchar_t)cValue;
304        /* wide  character  to multibyte character */
305        SECUREC_MASK_MSVC_CRT_WARNING
306        textLen = wctomb(buffer->str, wchar);
307        SECUREC_END_MASK_MSVC_CRT_WARNING
308        if (textLen < 0) {
309            return -1;
310        }
311    } else {
312        /* get  multibyte character from argument */
313        unsigned short temp;
314        temp = (unsigned short)cValue;
315        buffer->str[0] = (char)temp;
316        textLen = 1;
317    }
318    formatBuf->str = buffer->str;
319#endif
320
321    return textLen;
322}
323
324static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf)
325{
326    /* literal string to print null ptr, define it on stack rather than const text area
327       is to avoid gcc warning with pointing const text with variable */
328    static char strNullString[8] = "(null)";
329    static wchar_t wStrNullString[8] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' };
330
331    int finalPrecision;
332    char *strEnd = NULL;
333    wchar_t *wStrEnd = NULL;
334    int textLen;
335
336#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX))
337    attr->flags &= ~SECUREC_FLAG_LEADZERO;
338#endif
339    finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision;
340    formatBuf->str = argPtr;
341
342#ifdef SECUREC_FOR_WCHAR
343#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT)
344    if (!(attr->flags & SECUREC_FLAG_LONG)) {
345        attr->flags |= SECUREC_FLAG_SHORT;
346    }
347#endif
348    if (attr->flags & SECUREC_FLAG_SHORT) {
349        if (formatBuf->str == NULL) {   /* NULL passed, use special string */
350            formatBuf->str = strNullString;
351        }
352        strEnd = formatBuf->str;
353        for (textLen = 0; textLen < finalPrecision && *strEnd; textLen++) {
354            ++strEnd;
355        }
356        /* textLen now contains length in multibyte chars */
357    } else {
358        if (formatBuf->wStr == NULL) {  /* NULL passed, use special string */
359            formatBuf->wStr = wStrNullString;
360        }
361        attr->bufferIsWide = 1;
362        wStrEnd = formatBuf->wStr;
363        while (finalPrecision-- && *wStrEnd) {
364            ++wStrEnd;
365        }
366        textLen = (int)(wStrEnd - formatBuf->wStr); /* in wchar_ts */
367        /* textLen now contains length in wide chars */
368    }
369#else /* SECUREC_FOR_WCHAR */
370    if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
371        if (formatBuf->wStr == NULL) {  /* NULL passed, use special string */
372            formatBuf->wStr = wStrNullString;
373        }
374        attr->bufferIsWide = 1;
375        wStrEnd = formatBuf->wStr;
376        while (finalPrecision-- && *wStrEnd) {
377            ++wStrEnd;
378        }
379        textLen = (int)(wStrEnd - formatBuf->wStr);
380    } else {
381        if (formatBuf->str == NULL) {   /* meet NULL, use special string */
382            formatBuf->str = strNullString;
383        }
384
385        if (finalPrecision == SECUREC_INT_MAX) {
386            /* precision NOT assigned */
387            /* The strlen performance is high when the string length is greater than 32 */
388            textLen = (int)strlen(formatBuf->str);
389        } else {
390            /* precision assigned */
391            strEnd = formatBuf->str;
392            while (finalPrecision-- && *strEnd) {
393                ++strEnd;
394            }
395            textLen = (int)(strEnd - formatBuf->str);   /* length of the string */
396        }
397
398    }
399
400#endif /* SECUREC_FOR_WCHAR */
401    return textLen;
402}
403
404HILOG_LOCAL_API
405int SecOutputPS(SecPrintfStream *stream, int priv, const char *cformat, va_list arglist)
406{
407    const SecChar *format = cformat;
408
409    char *floatBuf = NULL;
410    SecFormatBuf formatBuf;
411    static const char *itoaUpperDigits = "0123456789ABCDEFX";
412    static const char *itoaLowerDigits = "0123456789abcdefx";
413    const char *digits = itoaUpperDigits;
414    int ii = 0;
415
416    unsigned int radix;
417    int charsOut;               /* characters written */
418
419    int prefixLen = 0;
420    int padding = 0;
421
422    int textLen;                /* length of the text */
423    int bufferSize = 0;         /* size of formatBuf.str */
424    int noOutput = 0;
425
426    SecFmtState state;
427    SecFmtState laststate;
428
429    SecChar prefix[2] = { 0 };
430    SecChar ch;                 /* currently read character */
431
432    static const unsigned char FMT_CHAR_TABLE[337] = {
433        /* type 0:    nospecial meaning;
434           1:   '%';
435           2:    '.'
436           3:    '*'
437           4:    '0'
438           5:    '1' ... '9'
439           6:    ' ', '+', '-', '#'
440           7:     'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j'
441           8:     'd','o','u','i','x','X','e','f','g'
442         */
443        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445        0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00,
446        0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
447        0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
448        0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
449        0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08,
450        0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
451        /* fill zero  for normal char 128 byte for 0x80 - 0xff */
452        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
453        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
454        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
455        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
456        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
457        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
458        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
459        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460        /* state  0: normal
461           1: percent
462           2: flag
463           3: width
464           4: dot
465           5: precis
466           6: size
467           7: type
468           8: invalid
469         */
470        0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
471        0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05,
472        0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03,
473        0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
474        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00,
475        0x00
476    };
477
478    SecFormatAttr formatAttr;
479    SecBuffer buffer;
480    formatAttr.flags = 0;
481    formatAttr.bufferIsWide = 0;    /* flag for buffer contains wide chars */
482    formatAttr.fldWidth = 0;
483    formatAttr.precision = 0;
484    formatAttr.dynWidth = 0;
485    formatAttr.dynPrecision = 0;
486
487    charsOut = 0;
488    textLen = 0;
489    state = STAT_NORMAL;        /* starting state */
490    formatBuf.str = NULL;
491
492    int isPrivacy = 1; /*whether show private string*/
493
494    /* loop each format character */
495    /* remove format != NULL */
496    while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) {
497        laststate = state;
498        state = SECUREC_DECODE_STATE(ch, FMT_CHAR_TABLE, laststate);
499
500        switch (state) {
501        case STAT_NORMAL:
502
503NORMAL_CHAR:
504
505            /* normal state, write character */
506            if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */ )) {
507                SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */
508            } else {
509#ifdef SECUREC_FOR_WCHAR
510                SECUREC_WRITE_CHAR(ch, stream, &charsOut);
511#else
512                /* optimize function call to code */
513                charsOut = -1;
514                stream->count = -1;
515#endif
516            }
517
518            continue;
519
520        case STAT_PERCENT:
521            /* set default values */
522            prefixLen = 0;
523            noOutput = 0;
524            formatAttr.flags = 0;
525            formatAttr.fldWidth = 0;
526            formatAttr.precision = -1;
527            formatAttr.bufferIsWide = 0;
528            if (*format == SECUREC_CHAR('{')) {
529                if (strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN) == 0) {
530                    isPrivacy = 0;
531                    format += PUBLIC_FLAG_LEN;
532                }
533                else if (strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN) == 0) {
534                    isPrivacy = 1;
535                    format += PRIVATE_FLAG_LEN;
536                }
537            }
538            else {
539                isPrivacy = 1;
540            }
541
542            if (priv == 0) {
543                isPrivacy = 0;
544            }
545
546            break;
547
548        case STAT_FLAG:
549            /* set flag based on which flag character */
550            SecDecodeFlags(ch, &formatAttr);
551            break;
552
553        case STAT_WIDTH:
554            /* update width value */
555            if (ch == SECUREC_CHAR('*')) {
556                /* get width */
557                formatAttr.fldWidth = (int)va_arg(arglist, int);
558                if (formatAttr.fldWidth < 0) {
559                    formatAttr.flags |= SECUREC_FLAG_LEFT;
560                    formatAttr.fldWidth = -formatAttr.fldWidth;
561                }
562                formatAttr.dynWidth = 1;
563            } else {
564                if (laststate != STAT_WIDTH) {
565                    formatAttr.fldWidth = 0;
566                }
567                if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) {
568                    return -1;
569                }
570                formatAttr.fldWidth = (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0'));
571                formatAttr.dynWidth = 0;
572            }
573            break;
574
575        case STAT_DOT:
576            formatAttr.precision = 0;
577            break;
578
579        case STAT_PRECIS:
580            /* update precision value */
581            if (ch == SECUREC_CHAR('*')) {
582                /* get precision from arg list */
583                formatAttr.precision = (int)va_arg(arglist, int);
584                if (formatAttr.precision < 0) {
585                    formatAttr.precision = -1;
586                }
587                formatAttr.dynPrecision = 1;
588            } else {
589                /* add digit to current precision */
590                if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) {
591                    return -1;
592                }
593                formatAttr.precision =
594                    (int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0'));
595                formatAttr.dynPrecision = 0;
596            }
597            break;
598
599        case STAT_SIZE:
600            /* read a size specifier, set the formatAttr.flags based on it */
601            if (SecDecodeSize(ch, &formatAttr, &format) != 0) {
602                /* Compatibility  code for "%I" just print I */
603                state = STAT_NORMAL;
604                goto NORMAL_CHAR;
605            }
606            break;
607
608        case STAT_TYPE:
609
610            switch (ch) {
611
612            case SECUREC_CHAR('C'):
613                /* wide char */
614                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
615
616#ifdef SECUREC_FOR_WCHAR
617                    formatAttr.flags |= SECUREC_FLAG_SHORT;
618#else
619                    formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
620#endif
621                }
622                /* fall-through */
623                /* FALLTHRU */
624            case SECUREC_CHAR('c'):
625                {
626                    unsigned int cValue = (unsigned int)va_arg(arglist, int);
627                    /*if it's a private arg, just write <priate> to stream*/
628                    if (isPrivacy == 1) {
629                        break;
630                    }
631                    textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer);
632                    if (textLen < 0) {
633                        noOutput = 1;
634                    }
635                }
636                break;
637            case SECUREC_CHAR('S'):    /* wide char string */
638#ifndef SECUREC_FOR_WCHAR
639                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
640                    formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
641                }
642#else
643                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
644                    formatAttr.flags |= SECUREC_FLAG_SHORT;
645                }
646#endif
647                /* fall-through */
648                /* FALLTHRU */
649            case SECUREC_CHAR('s'):
650                {
651                    char *argPtr = (char *)va_arg(arglist, char *);
652                    /*if it's a private arg, just write <priate> to stream*/
653                    if (isPrivacy == 1) {
654                        break;
655                    }
656                    textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf);
657                }
658                break;
659
660            case SECUREC_CHAR('n'):
661                /* higher risk disable it */
662                return -1;
663
664            case SECUREC_CHAR('E'):    /* fall-through */ /* FALLTHRU */
665            case SECUREC_CHAR('F'):    /* fall-through */ /* FALLTHRU */
666            case SECUREC_CHAR('G'):    /* fall-through */ /* FALLTHRU */
667            case SECUREC_CHAR('A'):    /* fall-through */ /* FALLTHRU */
668                /* convert format char to lower , use Explicit conversion to clean up compilation warning */
669                ch = (SecChar)(ch + ((SecChar)(SECUREC_CHAR('a')) - (SECUREC_CHAR('A'))));
670                /* fall-through */
671                /* FALLTHRU */
672            case SECUREC_CHAR('e'):    /* fall-through */ /* FALLTHRU */
673            case SECUREC_CHAR('f'):    /* fall-through */ /* FALLTHRU */
674            case SECUREC_CHAR('g'):    /* fall-through */ /* FALLTHRU */
675            case SECUREC_CHAR('a'):
676                {
677                    /*if it's a private arg, just write <priate> to stream*/
678                    if (isPrivacy == 1) {
679#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
680                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
681                            (void)va_arg(arglist, long double);
682                        } else
683#endif
684                        {
685                            (void)va_arg(arglist, double);
686                        }
687                        break;
688                    }
689
690                    /* floating point conversion */
691                    formatBuf.str = buffer.str; /* output buffer for float string with default size */
692
693                    /* compute the precision value */
694                    if (formatAttr.precision < 0) {
695                        formatAttr.precision = 6;
696                    } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) {
697                        formatAttr.precision = 1;
698                    }
699
700                    /* calc buffer size to store long double value */
701                    if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
702                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) {
703                            noOutput = 1;
704                            break;
705                        }
706                        bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision;
707                    } else {
708                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) {
709                            noOutput = 1;
710                            break;
711                        }
712                        bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision;
713                    }
714                    if (formatAttr.fldWidth > bufferSize) {
715                        bufferSize = formatAttr.fldWidth;
716                    }
717
718                    if (bufferSize >= SECUREC_BUFFER_SIZE) {
719                        /* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */
720                        /* size include '+' and '\0' */
721                        floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2));
722                        if (floatBuf != NULL) {
723                            formatBuf.str = floatBuf;
724                        } else {
725                            noOutput = 1;
726                            break;
727                        }
728                    }
729
730                    {
731                        /* add following code to call system sprintf API for float number */
732                        const SecChar *pFltFmt = format - 2;    /* point to the position before 'f' or 'g' */
733                        int k;
734                        int fltFmtStrLen;
735                        char fltFmtBuf[SECUREC_FMT_STR_LEN];
736                        char *fltFmtStr = fltFmtBuf;
737                        char *fltFmtHeap = NULL;    /* to clear warning */
738
739                        /* must meet '%' (normal format) or '}'(with{private} or{public} format)*/
740                        while (*pFltFmt != SECUREC_CHAR('%') && *pFltFmt != SECUREC_CHAR('}')) {
741                            --pFltFmt;
742                        }
743                        fltFmtStrLen = (int)((format - pFltFmt) + 1);   /* with ending terminator */
744                        if (fltFmtStrLen > SECUREC_FMT_STR_LEN) {
745                            /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */
746                            fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen));
747                            if (fltFmtHeap == NULL) {
748                                noOutput = 1;
749                                break;
750                            } else {
751                                fltFmtHeap[0] = '%';
752                                for (k = 1; k < fltFmtStrLen - 1; ++k) {
753                                    /* convert wchar to char */
754                                    fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */
755                                }
756                                fltFmtHeap[k] = '\0';
757
758                                fltFmtStr = fltFmtHeap;
759                            }
760                        } else {
761                            /* purpose of the repeat code is to solve the tool alarm  Redundant_Null_Check */
762                            fltFmtBuf[0] = '%';
763                            for (k = 1; k < fltFmtStrLen - 1; ++k) {
764                                /* convert wchar to char */
765                                fltFmtBuf[k] = (char)(pFltFmt[k]);  /* copy the format string */
766                            }
767                            fltFmtBuf[k] = '\0';
768                        }
769
770#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
771                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
772                            long double tmp = (long double)va_arg(arglist, long double);
773                            /* call system sprintf to format float value */
774                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
775                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
776                                                             formatAttr.fldWidth,formatAttr.precision, tmp);
777                            } else if (formatAttr.dynWidth) {
778                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
779                                                             formatAttr.fldWidth, tmp);
780                            } else if (formatAttr.dynPrecision) {
781                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
782                                                             formatAttr.precision, tmp);
783                            } else {
784                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
785                            }
786                        } else
787#endif
788                        {
789                            double tmp = (double)va_arg(arglist, double);
790                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
791                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
792                                                             formatAttr.precision, tmp);
793                            } else if (formatAttr.dynWidth) {
794                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
795                                                             tmp);
796                            } else if (formatAttr.dynPrecision) {
797                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision,
798                                                             tmp);
799                            } else {
800                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
801                            }
802                        }
803
804                        if (fltFmtHeap != NULL) {
805                            /* if buffer is allocated on heap, free it */
806                            SECUREC_FREE(fltFmtHeap);
807                            fltFmtHeap = NULL;
808                            /* to clear e438 last value assigned not used , the compiler will optimize this code */
809                            (void)fltFmtHeap;
810                        }
811                        if (textLen < 0) {
812                            /* bufferSize is large enough,just validation the return value */
813                            noOutput = 1;
814                            break;
815                        }
816
817                        formatAttr.fldWidth = textLen;  /* no padding ,this variable to calculate amount of padding */
818                        prefixLen = 0;  /* no padding ,this variable to  calculate amount of padding */
819                        formatAttr.flags = 0;   /* clear all internal formatAttr.flags */
820                        break;
821                    }
822                }
823
824            case SECUREC_CHAR('p'):
825                /* print a pointer */
826#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
827                formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
828#else
829                formatAttr.flags |= SECUREC_FLAG_POINTER;
830#endif
831
832#ifdef SECUREC_ON_64BITS
833                formatAttr.flags |= SECUREC_FLAG_I64;   /* converting an int64 */
834#else
835                formatAttr.flags |= SECUREC_FLAG_LONG;  /* converting a long */
836#endif
837
838#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX))
839
840#if defined(SECUREC_VXWORKS_PLATFORM)
841                formatAttr.precision = 1;
842#else
843                formatAttr.precision = 0;
844#endif
845                formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */
846                digits = itoaLowerDigits;
847                goto OUTPUT_HEX;
848#else
849/* not linux vxwoks */
850#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
851                formatAttr.precision = 1;
852#else
853                formatAttr.precision = 2 * sizeof(void *);
854#endif
855
856#endif
857
858#if defined(SECUREC_ON_UNIX)
859                digits = itoaLowerDigits;
860                goto OUTPUT_HEX;
861#endif
862
863                /* fall-through */
864                /* FALLTHRU */
865            case SECUREC_CHAR('X'):
866                /* unsigned upper hex output */
867                digits = itoaUpperDigits;
868                goto OUTPUT_HEX;
869            case SECUREC_CHAR('x'):
870                /* unsigned lower hex output */
871                digits = itoaLowerDigits;
872
873OUTPUT_HEX:
874                radix = 16;
875                if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
876                    /* alternate form means '0x' prefix */
877                    prefix[0] = SECUREC_CHAR('0');
878                    prefix[1] = (SecChar)(digits[16]); /* 'x' or 'X' */
879
880#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM))
881                    if (ch == 'p') {
882                        prefix[1] = SECUREC_CHAR('x');
883                    }
884#endif
885#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
886                    if (ch == 'p') {
887                        prefixLen = 0;
888                    } else {
889                        prefixLen = 2;
890                    }
891#else
892                    prefixLen = 2;
893#endif
894
895                }
896                goto OUTPUT_INT;
897            case SECUREC_CHAR('i'):    /* fall-through */ /* FALLTHRU */
898            case SECUREC_CHAR('d'):    /* fall-through */ /* FALLTHRU */
899                /* signed decimal output */
900                formatAttr.flags |= SECUREC_FLAG_SIGNED;
901                /* fall-through */
902                /* FALLTHRU */
903            case SECUREC_CHAR('u'):
904                radix = 10;
905                goto OUTPUT_INT;
906            case SECUREC_CHAR('o'):
907                /* unsigned octal output */
908                radix = 8;
909                if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
910                    /* alternate form means force a leading 0 */
911                    formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL;
912                }
913OUTPUT_INT:
914                {
915
916                    SecUnsignedInt64 number = 0;    /* number to convert */
917                    SecInt64 l; /* temp long value */
918                    unsigned char tch;
919#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)
920                    SecUnsignedInt32 digit = 0; /* ascii value of digit */
921                    SecUnsignedInt32 quotientHigh = 0;
922                    SecUnsignedInt32 quotientLow = 0;
923#endif
924
925                    /* read argument into variable l */
926                    if (formatAttr.flags & SECUREC_FLAG_I64) {
927                        l = (SecInt64)va_arg(arglist, SecInt64);
928                    } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) {
929                        l = (SecInt64)va_arg(arglist, SecInt64);
930                    } else
931#ifdef SECUREC_ON_64BITS
932                    if (formatAttr.flags & SECUREC_FLAG_LONG) {
933                        l = (long)va_arg(arglist, long);
934                    } else
935#endif /* SECUREC_ON_64BITS */
936                    if (formatAttr.flags & SECUREC_FLAG_CHAR) {
937                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
938                            l = (char)va_arg(arglist, int); /* sign extend */
939                            if (l >= 128) { /* on some platform, char is always unsigned */
940                                SecUnsignedInt64 tmpL = (SecUnsignedInt64)l;
941                                formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
942                                tch = (unsigned char)(~(tmpL));
943                                l = tch + 1;
944                            }
945                        } else {
946                            l = (unsigned char)va_arg(arglist, int);    /* zero-extend */
947                        }
948
949                    } else if (formatAttr.flags & SECUREC_FLAG_SHORT) {
950                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
951                            l = (short)va_arg(arglist, int);    /* sign extend */
952                        } else {
953                            l = (unsigned short)va_arg(arglist, int);   /* zero-extend */
954                        }
955
956                    }
957#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
958                    else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) {
959                        l = (ptrdiff_t)va_arg(arglist, ptrdiff_t);  /* sign extend */
960                    } else if (formatAttr.flags & SECUREC_FLAG_SIZE) {
961                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
962                            /* No suitable macros were found to handle the branch */
963                            if (SecIsSameSize(sizeof(size_t), sizeof(long))) {
964                                l = va_arg(arglist, long);  /* sign extend */
965                            } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) {
966                                l = va_arg(arglist, long long); /* sign extend */
967                            } else {
968                                l = va_arg(arglist, int);   /* sign extend */
969                            }
970                        } else {
971                            l = (SecInt64)(size_t)va_arg(arglist, size_t);  /* sign extend */
972                        }
973                    } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) {
974                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
975                            l = va_arg(arglist, SecInt64);  /* sign extend */
976                        } else {
977                            l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64);  /* sign extend */
978                        }
979                    }
980#endif
981                    else {
982                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
983                            l = va_arg(arglist, int);   /* sign extend */
984                        } else {
985                            l = (unsigned int)va_arg(arglist, int); /* zero-extend */
986                        }
987
988                    }
989                    /*if it's a private arg, just write <priate> to stream*/
990                    if (isPrivacy == 1) {
991                        break;
992                    }
993
994                    /* check for negative; copy into number */
995                    if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) {
996                        number = (SecUnsignedInt64)(-l);
997                        formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
998                    } else {
999                        number = (SecUnsignedInt64)l;
1000                    }
1001
1002                    if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) &&
1003#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
1004                        ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) &&
1005#endif
1006#ifdef SECUREC_ON_64BITS
1007                        ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) &&
1008                        ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) &&
1009#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT)  /* on window 64 system sizeof long is 32bit */
1010                        ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) &&
1011#endif
1012#endif
1013                        ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) {
1014
1015                            number &= 0xffffffff;
1016                    }
1017
1018                    /* check precision value for default */
1019                    if (formatAttr.precision < 0) {
1020                        formatAttr.precision = 1;   /* default precision */
1021                    } else {
1022#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1023                        formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1024#else
1025                        if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) {
1026                            formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1027                        }
1028#endif
1029                        if (formatAttr.precision > SECUREC_MAX_PRECISION) {
1030                            formatAttr.precision = SECUREC_MAX_PRECISION;
1031                        }
1032                    }
1033
1034                    /* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */
1035                    if (number == 0) {
1036#if !(defined(SECUREC_VXWORKS_PLATFORM)||defined(__hpux))
1037                        prefixLen = 0;
1038#else
1039                        if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE))
1040                            prefixLen = 2;
1041                        else
1042                            prefixLen = 0;
1043#endif
1044                    }
1045
1046                    /* Convert data to ASCII */
1047                    formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE];
1048
1049                    if (number > 0) {
1050#ifdef SECUREC_ON_64BITS
1051                        switch (radix) {
1052                            /* the compiler will optimize each one */
1053                            SECUREC_SPECIAL(number, 10);
1054                            break;
1055                            SECUREC_SPECIAL(number, 16);
1056                            break;
1057                            SECUREC_SPECIAL(number, 8);
1058                            break;
1059                        default:
1060                            break;
1061                        }
1062#else /* for 32 bits system */
1063                        if (number <= 0xFFFFFFFFUL) {
1064                            /* in most case, the value to be converted is small value */
1065                            SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number;
1066                            switch (radix) {
1067                                SECUREC_SPECIAL(n32Tmp, 16);
1068                                break;
1069                                SECUREC_SPECIAL(n32Tmp, 8);
1070                                break;
1071
1072#ifdef _AIX
1073                                /* the compiler will optimize div 10 */
1074                                SECUREC_SPECIAL(n32Tmp, 10);
1075                                break;
1076#else
1077                            case 10:
1078                                {
1079                                    /* fast div 10 */
1080                                    SecUnsignedInt32 q;
1081                                    SecUnsignedInt32 r;
1082                                    do {
1083                                        *--formatBuf.str = digits[n32Tmp % 10];
1084                                        q = (n32Tmp >> 1) + (n32Tmp >> 2);
1085                                        q = q + (q >> 4);
1086                                        q = q + (q >> 8);
1087                                        q = q + (q >> 16);
1088                                        q = q >> 3;
1089                                        r = n32Tmp - (((q << 2) + q) << 1);
1090                                        n32Tmp = (r > 9) ? (q + 1) : q;
1091                                    } while (n32Tmp != 0);
1092                                }
1093                                break;
1094#endif
1095                            default:
1096                                break;
1097                            }   /* end switch */
1098                        } else {
1099                            /* the value to be converted is greater than 4G */
1100#if defined(SECUREC_VXWORKS_VERSION_5_4)
1101                            do {
1102                                if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16),
1103                                                     (SecUnsignedInt32)number,
1104                                                     (SecUnsignedInt32)radix, &quotientHigh, &quotientLow, &digit)) {
1105                                    noOutput = 1;
1106                                    break;
1107                                }
1108                                *--formatBuf.str = digits[digit];
1109
1110                                number = (SecUnsignedInt64)quotientHigh;
1111                                number = (number << 32) + quotientLow;
1112                            } while (number != 0);
1113#else
1114                            switch (radix) {
1115                                /* the compiler will optimize div 10 */
1116                                SECUREC_SPECIAL(number, 10);
1117                                break;
1118                                SECUREC_SPECIAL(number, 16);
1119                                break;
1120                                SECUREC_SPECIAL(number, 8);
1121                                break;
1122                            default:
1123                                break;
1124                            }
1125#endif
1126                        }
1127#endif
1128                    }           /* END if (number > 0) */
1129                    /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */
1130                    textLen = (int)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str);
1131                    if (formatAttr.precision > textLen) {
1132                        for (ii = 0; ii < formatAttr.precision - textLen; ++ii) {
1133                            *--formatBuf.str = '0';
1134                        }
1135                        textLen = formatAttr.precision;
1136                    }
1137
1138                    /* Force a leading zero if FORCEOCTAL flag set */
1139                    if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && (textLen == 0 || formatBuf.str[0] != '0')) {
1140                        *--formatBuf.str = '0';
1141                        ++textLen;  /* add a zero */
1142                    }
1143                }
1144                break;
1145            default:
1146                break;
1147            }
1148            /*if it's a private arg, just write <priate> to stream*/
1149            if (isPrivacy == 1) {
1150                SecWritePrivateStr(stream, &charsOut);
1151                break;
1152            }
1153
1154            if (noOutput == 0) {
1155                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1156                    if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) {
1157                        /* prefix is a '-' */
1158                        prefix[0] = SECUREC_CHAR('-');
1159                        prefixLen = 1;
1160                    } else if (formatAttr.flags & SECUREC_FLAG_SIGN) {
1161                        /* prefix is '+' */
1162                        prefix[0] = SECUREC_CHAR('+');
1163                        prefixLen = 1;
1164                    } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) {
1165                        /* prefix is ' ' */
1166                        prefix[0] = SECUREC_CHAR(' ');
1167                        prefixLen = 1;
1168                    }
1169                }
1170
1171#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX))
1172                if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (0 == textLen)) {
1173                    formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1174                    formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1];
1175                    *formatBuf.str-- = '\0';
1176                    *formatBuf.str-- = ')';
1177                    *formatBuf.str-- = 'l';
1178                    *formatBuf.str-- = 'i';
1179                    *formatBuf.str-- = 'n';
1180                    *formatBuf.str = '(';
1181                    textLen = 5;
1182                }
1183#endif
1184
1185                /* calculate amount of padding */
1186                padding = (formatAttr.fldWidth - textLen) - prefixLen;
1187
1188                /* put out the padding, prefix, and text, in the correct order */
1189
1190                if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) {
1191                    /* pad on left with blanks */
1192                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1193                        /* char * cast to wchar * */
1194                        SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1195                    } else {
1196                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1197                    }
1198                }
1199
1200                /* write prefix */
1201                if (prefixLen > 0) {
1202                    SecChar *pPrefix = prefix;
1203                    if (SECUREC_IS_REST_BUF_ENOUGH(prefixLen)) {
1204                        /* max prefix len is 2, use loop copy */ /* char * cast to wchar * */
1205                        SECUREC_SAFE_WRITE_PREFIX(pPrefix, prefixLen, stream, &charsOut);
1206                    } else {
1207                        SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut);
1208                    }
1209                }
1210
1211                if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT)
1212                    && padding > 0) {
1213                    /* write leading zeros */
1214                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1215                        /* char * cast to wchar * */
1216                        SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut);
1217                    } else {
1218                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut);
1219                    }
1220                }
1221
1222                /* write text */
1223#ifndef SECUREC_FOR_WCHAR
1224                if (formatAttr.bufferIsWide && (textLen > 0)) {
1225                    wchar_t *p = formatBuf.wStr;
1226                    int count = textLen;
1227                    while (count--) {
1228                        char tmpBuf[SECUREC_MB_LEN + 1];
1229                        SECUREC_MASK_MSVC_CRT_WARNING
1230                        int retVal = wctomb(tmpBuf, *p++);
1231                        SECUREC_END_MASK_MSVC_CRT_WARNING
1232                        if (retVal <= 0) {
1233                            charsOut = -1;
1234                            break;
1235                        }
1236                        SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut);
1237                    }
1238                } else {
1239                    if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1240                        SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut);
1241                    } else {
1242                        SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut);
1243                    }
1244                }
1245#else /* SECUREC_FOR_WCHAR */
1246                if (formatAttr.bufferIsWide == 0 && textLen > 0) {
1247                    int count = textLen;
1248                    char *p = formatBuf.str;
1249
1250                    while (count > 0) {
1251                        wchar_t wchar = L'\0';
1252                        int retVal = mbtowc(&wchar, p, (size_t)MB_CUR_MAX);
1253                        if (retVal <= 0) {
1254                            charsOut = -1;
1255                            break;
1256                        }
1257                        SECUREC_WRITE_CHAR(wchar, stream, &charsOut);
1258                        p += retVal;
1259                        count -= retVal;
1260                    }
1261                } else {
1262                    if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1263                        SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); /* char * cast to wchar * */
1264                    } else {
1265                        SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut);
1266                    }
1267                }
1268#endif /* SECUREC_FOR_WCHAR */
1269
1270                if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) {
1271                    /* pad on right with blanks */
1272                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1273                        /* char * cast to wchar * */
1274                        SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1275                    } else {
1276                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1277                    }
1278                }
1279
1280                /* we're done! */
1281            }
1282            if (floatBuf != NULL) {
1283                SECUREC_FREE(floatBuf);
1284                floatBuf = NULL;
1285            }
1286            break;
1287        case STAT_INVALID:
1288            return -1;
1289        default:
1290            return -1;          /* input format is wrong, directly return */
1291        }
1292    }
1293
1294    if (state != STAT_NORMAL && state != STAT_TYPE) {
1295        return -1;
1296    }
1297
1298    return charsOut;            /* the number of characters written */
1299}                               /* arglist must not be declare as const */
1300#endif /* OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */
1301
1302