• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2022 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 privacyString[] = "<private>";
160    const char *pPrivStr = privacyString;
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'):
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        break;
261
262    case SECUREC_CHAR('w'):
263        attr->flags |= SECUREC_FLAG_WIDECHAR;   /* wide char */
264        break;
265    default:
266        break;
267
268    }
269
270    return 0;
271}
272
273static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer)
274{
275    int textLen;
276    wchar_t wchar;
277
278#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS))
279    attr->flags &= ~SECUREC_FLAG_LEADZERO;
280#endif
281
282#ifdef SECUREC_FOR_WCHAR
283    attr->bufferIsWide = 1;
284    wchar = (wchar_t)cValue;
285    if (attr->flags & SECUREC_FLAG_SHORT) {
286        /* multibyte character to wide  character */
287        char tempchar[2];
288        tempchar[0] = (char)(wchar & 0x00ff);
289        tempchar[1] = '\0';
290
291        if (mbtowc(buffer->wStr, tempchar, sizeof(tempchar)) < 0) {
292            return -1;
293        }
294    } else {
295        buffer->wStr[0] = wchar;
296    }
297    formatBuf->wStr = buffer->wStr;
298    textLen = 1;                /* only 1 wide character */
299#else
300    attr->bufferIsWide = 0;
301    if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
302        wchar = (wchar_t)cValue;
303        /* wide  character  to multibyte character */
304        SECUREC_MASK_MSVC_CRT_WARNING
305        textLen = wctomb(buffer->str, wchar);
306        SECUREC_END_MASK_MSVC_CRT_WARNING
307        if (textLen < 0) {
308            return -1;
309        }
310    } else {
311        /* get  multibyte character from argument */
312        unsigned short temp;
313        temp = (unsigned short)cValue;
314        buffer->str[0] = (char)temp;
315        textLen = 1;
316    }
317    formatBuf->str = buffer->str;
318#endif
319
320    return textLen;
321}
322
323static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf)
324{
325    /* literal string to print null ptr, define it on stack rather than const text area
326       is to avoid gcc warning with pointing const text with variable */
327    static char strNullString[8] = "(null)";
328    static wchar_t wStrNullString[8] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' };
329
330    int finalPrecision;
331    char *strEnd = NULL;
332    wchar_t *wStrEnd = NULL;
333    int textLen;
334
335#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX))
336    attr->flags &= ~SECUREC_FLAG_LEADZERO;
337#endif
338    finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision;
339    formatBuf->str = argPtr;
340
341#ifdef SECUREC_FOR_WCHAR
342#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT)
343    if (!(attr->flags & SECUREC_FLAG_LONG)) {
344        attr->flags |= SECUREC_FLAG_SHORT;
345    }
346#endif
347    if (attr->flags & SECUREC_FLAG_SHORT) {
348        if (formatBuf->str == NULL) {   /* NULL passed, use special string */
349            formatBuf->str = strNullString;
350        }
351        strEnd = formatBuf->str;
352        for (textLen = 0; textLen < finalPrecision && *strEnd; textLen++) {
353            ++strEnd;
354        }
355        /* textLen now contains length in multibyte chars */
356    } else {
357        if (formatBuf->wStr == NULL) {  /* NULL passed, use special string */
358            formatBuf->wStr = wStrNullString;
359        }
360        attr->bufferIsWide = 1;
361        wStrEnd = formatBuf->wStr;
362        while (finalPrecision-- && *wStrEnd) {
363            ++wStrEnd;
364        }
365        textLen = (int)(wStrEnd - formatBuf->wStr); /* in wchar_ts */
366        /* textLen now contains length in wide chars */
367    }
368#else /* SECUREC_FOR_WCHAR */
369    if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) {
370        if (formatBuf->wStr == NULL) {  /* NULL passed, use special string */
371            formatBuf->wStr = wStrNullString;
372        }
373        attr->bufferIsWide = 1;
374        wStrEnd = formatBuf->wStr;
375        while (finalPrecision-- && *wStrEnd) {
376            ++wStrEnd;
377        }
378        textLen = (int)(wStrEnd - formatBuf->wStr);
379    } else {
380        if (formatBuf->str == NULL) {   /* meet NULL, use special string */
381            formatBuf->str = strNullString;
382        }
383
384        if (finalPrecision == SECUREC_INT_MAX) {
385            /* precision NOT assigned */
386            /* The strlen performance is high when the string length is greater than 32 */
387            textLen = (int)strlen(formatBuf->str);
388        } else {
389            /* precision assigned */
390            strEnd = formatBuf->str;
391            while (finalPrecision-- && *strEnd) {
392                ++strEnd;
393            }
394            textLen = (int)(strEnd - formatBuf->str);   /* length of the string */
395        }
396
397    }
398
399#endif /* SECUREC_FOR_WCHAR */
400    return textLen;
401}
402
403HILOG_LOCAL_API
404int SecOutputPS(SecPrintfStream *stream, int priv, const char *cformat, va_list arglist)
405{
406    const SecChar *format = cformat;
407
408    char *floatBuf = NULL;
409    SecFormatBuf formatBuf;
410    static const char *itoaUpperDigits = "0123456789ABCDEFX";
411    static const char *itoaLowerDigits = "0123456789abcdefx";
412    const char *digits = itoaUpperDigits;
413    int ii = 0;
414
415    unsigned int radix;
416    int charsOut;               /* characters written */
417
418    int prefixLen = 0;
419    int padding = 0;
420
421    int textLen;                /* length of the text */
422    int bufferSize = 0;         /* size of formatBuf.str */
423    int noOutput = 0;
424
425    SecFmtState state;
426    SecFmtState laststate;
427
428    SecChar prefix[2] = { 0 };
429    SecChar ch;                 /* currently read character */
430
431    static const unsigned char fmtCharTable[337] = {
432        /* type 0:    nospecial meaning;
433           1:   '%';
434           2:    '.'
435           3:    '*'
436           4:    '0'
437           5:    '1' ... '9'
438           6:    ' ', '+', '-', '#'
439           7:     'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j'
440           8:     'd','o','u','i','x','X','e','f','g'
441         */
442        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444        0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00,
445        0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446        0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
447        0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
448        0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08,
449        0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
450        /* fill zero  for normal char 128 byte for 0x80 - 0xff */
451        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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        /* state  0: normal
460           1: percent
461           2: flag
462           3: width
463           4: dot
464           5: precis
465           6: size
466           7: type
467           8: invalid
468         */
469        0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
470        0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05,
471        0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03,
472        0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
473        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00,
474        0x00
475    };
476
477    SecFormatAttr formatAttr;
478    SecBuffer buffer;
479    formatAttr.flags = 0;
480    formatAttr.bufferIsWide = 0;    /* flag for buffer contains wide chars */
481    formatAttr.fldWidth = 0;
482    formatAttr.precision = 0;
483    formatAttr.dynWidth = 0;
484    formatAttr.dynPrecision = 0;
485
486    charsOut = 0;
487    textLen = 0;
488    state = STAT_NORMAL;        /* starting state */
489    formatBuf.str = NULL;
490
491    int isPrivacy = 1; /*whether show private string*/
492
493    /* loop each format character */
494    /* remove format != NULL */
495    while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) {
496        laststate = state;
497        state = SECUREC_DECODE_STATE(ch, fmtCharTable, laststate);
498
499        switch (state) {
500        case STAT_NORMAL:
501
502NORMAL_CHAR:
503
504            /* normal state, write character */
505            if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */ )) {
506                SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */
507            } else {
508#ifdef SECUREC_FOR_WCHAR
509                SECUREC_WRITE_CHAR(ch, stream, &charsOut);
510#else
511                /* optimize function call to code */
512                charsOut = -1;
513                stream->count = -1;
514#endif
515            }
516
517            continue;
518
519        case STAT_PERCENT:
520            /* set default values */
521            prefixLen = 0;
522            noOutput = 0;
523            formatAttr.flags = 0;
524            formatAttr.fldWidth = 0;
525            formatAttr.precision = -1;
526            formatAttr.bufferIsWide = 0;
527            if (*format == SECUREC_CHAR('{')) {
528                if (strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN) == 0) {
529                    isPrivacy = 0;
530                    format += PUBLIC_FLAG_LEN;
531                }
532                else if (strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN) == 0) {
533                    isPrivacy = 1;
534                    format += PRIVATE_FLAG_LEN;
535                }
536            }
537            else {
538                isPrivacy = 1;
539            }
540
541            if (0 == priv) {
542                isPrivacy = 0;
543            }
544
545            break;
546
547        case STAT_FLAG:
548            /* set flag based on which flag character */
549            SecDecodeFlags(ch, &formatAttr);
550            break;
551
552        case STAT_WIDTH:
553            /* update width value */
554            if (ch == SECUREC_CHAR('*')) {
555                /* get width */
556                formatAttr.fldWidth = (int)va_arg(arglist, int);
557                if (formatAttr.fldWidth < 0) {
558                    formatAttr.flags |= SECUREC_FLAG_LEFT;
559                    formatAttr.fldWidth = -formatAttr.fldWidth;
560                }
561                formatAttr.dynWidth = 1;
562            } else {
563                if (laststate != STAT_WIDTH) {
564                    formatAttr.fldWidth = 0;
565                }
566                if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) {
567                    return -1;
568                }
569                formatAttr.fldWidth = (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0'));
570                formatAttr.dynWidth = 0;
571            }
572            break;
573
574        case STAT_DOT:
575            formatAttr.precision = 0;
576            break;
577
578        case STAT_PRECIS:
579            /* update precision value */
580            if (ch == SECUREC_CHAR('*')) {
581                /* get precision from arg list */
582                formatAttr.precision = (int)va_arg(arglist, int);
583                if (formatAttr.precision < 0) {
584                    formatAttr.precision = -1;
585                }
586                formatAttr.dynPrecision = 1;
587            } else {
588                /* add digit to current precision */
589                if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) {
590                    return -1;
591                }
592                formatAttr.precision =
593                    (int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0'));
594                formatAttr.dynPrecision = 0;
595            }
596            break;
597
598        case STAT_SIZE:
599            /* read a size specifier, set the formatAttr.flags based on it */
600            if (SecDecodeSize(ch, &formatAttr, &format) != 0) {
601                /* Compatibility  code for "%I" just print I */
602                state = STAT_NORMAL;
603                goto NORMAL_CHAR;
604            }
605            break;
606
607        case STAT_TYPE:
608
609            switch (ch) {
610
611            case SECUREC_CHAR('C'):
612                /* wide char */
613                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
614
615#ifdef SECUREC_FOR_WCHAR
616                    formatAttr.flags |= SECUREC_FLAG_SHORT;
617#else
618                    formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
619#endif
620                }
621                /* fall-through */
622                /* FALLTHRU */
623            case SECUREC_CHAR('c'):
624                {
625                    unsigned int cValue = (unsigned int)va_arg(arglist, int);
626                    /*if it's a private arg, just write <priate> to stream*/
627                    if (isPrivacy == 1) {
628                        break;
629                    }
630                    textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer);
631                    if (textLen < 0) {
632                        noOutput = 1;
633                    }
634                }
635                break;
636            case SECUREC_CHAR('S'):    /* wide char string */
637#ifndef SECUREC_FOR_WCHAR
638                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
639                    formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
640                }
641#else
642                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
643                    formatAttr.flags |= SECUREC_FLAG_SHORT;
644                }
645#endif
646                /* fall-through */
647                /* FALLTHRU */
648            case SECUREC_CHAR('s'):
649                {
650                    char *argPtr = (char *)va_arg(arglist, char *);
651                    /*if it's a private arg, just write <priate> to stream*/
652                    if (isPrivacy == 1) {
653                        break;
654                    }
655                    textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf);
656                }
657                break;
658
659            case SECUREC_CHAR('n'):
660                /* higher risk disable it */
661                return -1;
662
663            case SECUREC_CHAR('E'):    /* fall-through */ /* FALLTHRU */
664            case SECUREC_CHAR('F'):    /* fall-through */ /* FALLTHRU */
665            case SECUREC_CHAR('G'):    /* fall-through */ /* FALLTHRU */
666            case SECUREC_CHAR('A'):    /* fall-through */ /* FALLTHRU */
667                /* convert format char to lower , use Explicit conversion to clean up compilation warning */
668                ch = (SecChar) (ch + ((SecChar) (SECUREC_CHAR('a')) - (SECUREC_CHAR('A'))));
669                /* fall-through */
670                /* FALLTHRU */
671            case SECUREC_CHAR('e'):    /* fall-through */ /* FALLTHRU */
672            case SECUREC_CHAR('f'):    /* fall-through */ /* FALLTHRU */
673            case SECUREC_CHAR('g'):    /* fall-through */ /* FALLTHRU */
674            case SECUREC_CHAR('a'):
675                {
676                    /*if it's a private arg, just write <priate> to stream*/
677                    if (isPrivacy == 1) {
678#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
679                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
680                            (void)va_arg(arglist, long double);
681                        } else
682#endif
683                        {
684                            (void)va_arg(arglist, double);
685                        }
686                        break;
687                    }
688
689                    /* floating point conversion */
690                    formatBuf.str = buffer.str; /* output buffer for float string with default size */
691
692                    /* compute the precision value */
693                    if (formatAttr.precision < 0) {
694                        formatAttr.precision = 6;
695                    } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) {
696                        formatAttr.precision = 1;
697                    }
698
699                    /* calc buffer size to store long double value */
700                    if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
701                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) {
702                            noOutput = 1;
703                            break;
704                        }
705                        bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision;
706                    } else {
707                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) {
708                            noOutput = 1;
709                            break;
710                        }
711                        bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision;
712                    }
713                    if (formatAttr.fldWidth > bufferSize) {
714                        bufferSize = formatAttr.fldWidth;
715                    }
716
717                    if (bufferSize >= SECUREC_BUFFER_SIZE) {
718                        /* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */
719                        /* size include '+' and '\0' */
720                        floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2));
721                        if (floatBuf != NULL) {
722                            formatBuf.str = floatBuf;
723                        } else {
724                            noOutput = 1;
725                            break;
726                        }
727                    }
728
729                    {
730                        /* add following code to call system sprintf API for float number */
731                        const SecChar *pFltFmt = format - 2;    /* point to the position before 'f' or 'g' */
732                        int k;
733                        int fltFmtStrLen;
734                        char fltFmtBuf[SECUREC_FMT_STR_LEN];
735                        char *fltFmtStr = fltFmtBuf;
736                        char *fltFmtHeap = NULL;    /* to clear warning */
737
738                        /* must meet '%' (normal format) or '}'(with{private} or{public} format)*/
739                        while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) {
740                            --pFltFmt;
741                        }
742                        fltFmtStrLen = (int)((format - pFltFmt) + 1);   /* with ending terminator */
743                        if (fltFmtStrLen > SECUREC_FMT_STR_LEN) {
744                            /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */
745                            fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen));
746                            if (fltFmtHeap == NULL) {
747                                noOutput = 1;
748                                break;
749                            } else {
750                                fltFmtHeap[0] = '%';
751                                for (k = 1; k < fltFmtStrLen - 1; ++k) {
752                                    /* convert wchar to char */
753                                    fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */
754                                }
755                                fltFmtHeap[k] = '\0';
756
757                                fltFmtStr = fltFmtHeap;
758                            }
759                        } else {
760                            /* purpose of the repeat code is to solve the tool alarm  Redundant_Null_Check */
761                            fltFmtBuf[0] = '%';
762                            for (k = 1; k < fltFmtStrLen - 1; ++k) {
763                                /* convert wchar to char */
764                                fltFmtBuf[k] = (char)(pFltFmt[k]);  /* copy the format string */
765                            }
766                            fltFmtBuf[k] = '\0';
767                        }
768
769#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
770                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
771                            long double tmp = (long double)va_arg(arglist, long double);
772                            /* call system sprintf to format float value */
773                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
774                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
775                                                             formatAttr.fldWidth,formatAttr.precision, tmp);
776                            } else if (formatAttr.dynWidth) {
777                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
778                                                             formatAttr.fldWidth, tmp);
779                            } else if (formatAttr.dynPrecision) {
780                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
781                                                             formatAttr.precision, tmp);
782                            } else {
783                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
784                            }
785                        } else
786#endif
787                        {
788                            double tmp = (double)va_arg(arglist, double);
789                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
790                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
791                                                             formatAttr.precision, tmp);
792                            } else if (formatAttr.dynWidth) {
793                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
794                                                             tmp);
795                            } else if (formatAttr.dynPrecision) {
796                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision,
797                                                             tmp);
798                            } else {
799                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
800                            }
801                        }
802
803                        if (fltFmtHeap != NULL) {
804                            /* if buffer is allocated on heap, free it */
805                            SECUREC_FREE(fltFmtHeap);
806                            fltFmtHeap = NULL;
807                            /* to clear e438 last value assigned not used , the compiler will optimize this code */
808                            (void)fltFmtHeap;
809                        }
810                        if (textLen < 0) {
811                            /* bufferSize is large enough,just validation the return value */
812                            noOutput = 1;
813                            break;
814                        }
815
816                        formatAttr.fldWidth = textLen;  /* no padding ,this variable to calculate amount of padding */
817                        prefixLen = 0;  /* no padding ,this variable to  calculate amount of padding */
818                        formatAttr.flags = 0;   /* clear all internal formatAttr.flags */
819                        break;
820                    }
821                }
822
823            case SECUREC_CHAR('p'):
824                /* print a pointer */
825#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
826                formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
827#else
828                formatAttr.flags |= SECUREC_FLAG_POINTER;
829#endif
830
831#ifdef SECUREC_ON_64BITS
832                formatAttr.flags |= SECUREC_FLAG_I64;   /* converting an int64 */
833#else
834                formatAttr.flags |= SECUREC_FLAG_LONG;  /* converting a long */
835#endif
836
837#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX))
838
839#if defined(SECUREC_VXWORKS_PLATFORM)
840                formatAttr.precision = 1;
841#else
842                formatAttr.precision = 0;
843#endif
844                formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */
845                digits = itoaLowerDigits;
846                goto OUTPUT_HEX;
847#else
848/* not linux vxwoks */
849#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
850                formatAttr.precision = 1;
851#else
852                formatAttr.precision = 2 * sizeof(void *);
853#endif
854
855#endif
856
857#if defined(SECUREC_ON_UNIX)
858                digits = itoaLowerDigits;
859                goto OUTPUT_HEX;
860#endif
861
862                /* fall-through */
863                /* FALLTHRU */
864            case SECUREC_CHAR('X'):
865                /* unsigned upper hex output */
866                digits = itoaUpperDigits;
867                goto OUTPUT_HEX;
868            case SECUREC_CHAR('x'):
869                /* unsigned lower hex output */
870                digits = itoaLowerDigits;
871
872OUTPUT_HEX:
873                radix = 16;
874                if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
875                    /* alternate form means '0x' prefix */
876                    prefix[0] = SECUREC_CHAR('0');
877                    prefix[1] = (SecChar) (digits[16]); /* 'x' or 'X' */
878
879#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM))
880                    if (ch == 'p') {
881                        prefix[1] = SECUREC_CHAR('x');
882                    }
883#endif
884#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
885                    if (ch == 'p') {
886                        prefixLen = 0;
887                    } else {
888                        prefixLen = 2;
889                    }
890#else
891                    prefixLen = 2;
892#endif
893
894                }
895                goto OUTPUT_INT;
896            case SECUREC_CHAR('i'):    /* fall-through */ /* FALLTHRU */
897            case SECUREC_CHAR('d'):    /* fall-through */ /* FALLTHRU */
898                /* signed decimal output */
899                formatAttr.flags |= SECUREC_FLAG_SIGNED;
900                /* fall-through */
901                /* FALLTHRU */
902            case SECUREC_CHAR('u'):
903                radix = 10;
904                goto OUTPUT_INT;
905            case SECUREC_CHAR('o'):
906                /* unsigned octal output */
907                radix = 8;
908                if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
909                    /* alternate form means force a leading 0 */
910                    formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL;
911                }
912OUTPUT_INT:
913                {
914
915                    SecUnsignedInt64 number = 0;    /* number to convert */
916                    SecInt64 l; /* temp long value */
917                    unsigned char tch;
918#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)
919                    SecUnsignedInt32 digit = 0; /* ascii value of digit */
920                    SecUnsignedInt32 quotientHigh = 0;
921                    SecUnsignedInt32 quotientLow = 0;
922#endif
923
924                    /* read argument into variable l */
925                    if (formatAttr.flags & SECUREC_FLAG_I64) {
926                        l = (SecInt64)va_arg(arglist, SecInt64);
927                    } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) {
928                        l = (SecInt64)va_arg(arglist, SecInt64);
929                    } else
930#ifdef SECUREC_ON_64BITS
931                    if (formatAttr.flags & SECUREC_FLAG_LONG) {
932                        l = (long)va_arg(arglist, long);
933                    } else
934#endif /* SECUREC_ON_64BITS */
935                    if (formatAttr.flags & SECUREC_FLAG_CHAR) {
936                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
937                            l = (char)va_arg(arglist, int); /* sign extend */
938                            if (l >= 128) { /* on some platform, char is always unsigned */
939                                SecUnsignedInt64 tmpL = (SecUnsignedInt64)l;
940                                formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
941                                tch = (unsigned char)(~(tmpL));
942                                l = tch + 1;
943                            }
944                        } else {
945                            l = (unsigned char)va_arg(arglist, int);    /* zero-extend */
946                        }
947
948                    } else if (formatAttr.flags & SECUREC_FLAG_SHORT) {
949                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
950                            l = (short)va_arg(arglist, int);    /* sign extend */
951                        } else {
952                            l = (unsigned short)va_arg(arglist, int);   /* zero-extend */
953                        }
954
955                    }
956#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
957                    else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) {
958                        l = (ptrdiff_t)va_arg(arglist, ptrdiff_t);  /* sign extend */
959                    } else if (formatAttr.flags & SECUREC_FLAG_SIZE) {
960                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
961                            /* No suitable macros were found to handle the branch */
962                            if (SecIsSameSize(sizeof(size_t), sizeof(long))) {
963                                l = va_arg(arglist, long);  /* sign extend */
964                            } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) {
965                                l = va_arg(arglist, long long); /* sign extend */
966                            } else {
967                                l = va_arg(arglist, int);   /* sign extend */
968                            }
969                        } else {
970                            l = (SecInt64)(size_t)va_arg(arglist, size_t);  /* sign extend */
971                        }
972                    } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) {
973                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
974                            l = va_arg(arglist, SecInt64);  /* sign extend */
975                        } else {
976                            l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64);  /* sign extend */
977                        }
978                    }
979#endif
980                    else {
981                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
982                            l = va_arg(arglist, int);   /* sign extend */
983                        } else {
984                            l = (unsigned int)va_arg(arglist, int); /* zero-extend */
985                        }
986
987                    }
988                    /*if it's a private arg, just write <priate> to stream*/
989                    if (isPrivacy == 1) {
990                        break;
991                    }
992
993                    /* check for negative; copy into number */
994                    if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) {
995                        number = (SecUnsignedInt64)(-l);
996                        formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
997                    } else {
998                        number = (SecUnsignedInt64)l;
999                    }
1000
1001                    if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) &&
1002#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
1003                        ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) &&
1004#endif
1005#ifdef SECUREC_ON_64BITS
1006                        ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) &&
1007                        ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) &&
1008#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT)  /* on window 64 system sizeof long is 32bit */
1009                        ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) &&
1010#endif
1011#endif
1012                        ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) {
1013
1014                            number &= 0xffffffff;
1015                    }
1016
1017                    /* check precision value for default */
1018                    if (formatAttr.precision < 0) {
1019                        formatAttr.precision = 1;   /* default precision */
1020                    } else {
1021#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1022                        formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1023#else
1024                        if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) {
1025                            formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1026                        }
1027#endif
1028                        if (formatAttr.precision > SECUREC_MAX_PRECISION) {
1029                            formatAttr.precision = SECUREC_MAX_PRECISION;
1030                        }
1031                    }
1032
1033                    /* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */
1034                    if (number == 0) {
1035#if !(defined(SECUREC_VXWORKS_PLATFORM)||defined(__hpux))
1036                        prefixLen = 0;
1037#else
1038                        if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE))
1039                            prefixLen = 2;
1040                        else
1041                            prefixLen = 0;
1042#endif
1043                    }
1044
1045                    /* Convert data to ASCII */
1046                    formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE];
1047
1048                    if (number > 0) {
1049#ifdef SECUREC_ON_64BITS
1050                        switch (radix) {
1051                            /* the compiler will optimize each one */
1052                            SECUREC_SPECIAL(number, 10);
1053                            break;
1054                            SECUREC_SPECIAL(number, 16);
1055                            break;
1056                            SECUREC_SPECIAL(number, 8);
1057                            break;
1058                        default:
1059                            break;
1060                        }
1061#else /* for 32 bits system */
1062                        if (number <= 0xFFFFFFFFUL) {
1063                            /* in most case, the value to be converted is small value */
1064                            SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number;
1065                            switch (radix) {
1066                                SECUREC_SPECIAL(n32Tmp, 16);
1067                                break;
1068                                SECUREC_SPECIAL(n32Tmp, 8);
1069                                break;
1070
1071#ifdef _AIX
1072                                /* the compiler will optimize div 10 */
1073                                SECUREC_SPECIAL(n32Tmp, 10);
1074                                break;
1075#else
1076                            case 10:
1077                                {
1078                                    /* fast div 10 */
1079                                    SecUnsignedInt32 q;
1080                                    SecUnsignedInt32 r;
1081                                    do {
1082                                        *--formatBuf.str = digits[n32Tmp % 10];
1083                                        q = (n32Tmp >> 1) + (n32Tmp >> 2);
1084                                        q = q + (q >> 4);
1085                                        q = q + (q >> 8);
1086                                        q = q + (q >> 16);
1087                                        q = q >> 3;
1088                                        r = n32Tmp - (((q << 2) + q) << 1);
1089                                        n32Tmp = (r > 9) ? (q + 1) : q;
1090                                    } while (n32Tmp != 0);
1091                                }
1092                                break;
1093#endif
1094                            default:
1095                                break;
1096                            }   /* end switch */
1097                        } else {
1098                            /* the value to be converted is greater than 4G */
1099#if defined(SECUREC_VXWORKS_VERSION_5_4)
1100                            do {
1101                                if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16),
1102                                                     (SecUnsignedInt32)number,
1103                                                     (SecUnsignedInt32)radix, &quotientHigh, &quotientLow, &digit)) {
1104                                    noOutput = 1;
1105                                    break;
1106                                }
1107                                *--formatBuf.str = digits[digit];
1108
1109                                number = (SecUnsignedInt64)quotientHigh;
1110                                number = (number << 32) + quotientLow;
1111                            } while (number != 0);
1112#else
1113                            switch (radix) {
1114                                /* the compiler will optimize div 10 */
1115                                SECUREC_SPECIAL(number, 10);
1116                                break;
1117                                SECUREC_SPECIAL(number, 16);
1118                                break;
1119                                SECUREC_SPECIAL(number, 8);
1120                                break;
1121                            default:
1122                                break;
1123                            }
1124#endif
1125                        }
1126#endif
1127                    }           /* END if (number > 0) */
1128                    /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */
1129                    textLen = (int)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str);
1130                    if (formatAttr.precision > textLen) {
1131                        for (ii = 0; ii < formatAttr.precision - textLen; ++ii) {
1132                            *--formatBuf.str = '0';
1133                        }
1134                        textLen = formatAttr.precision;
1135                    }
1136
1137                    /* Force a leading zero if FORCEOCTAL flag set */
1138                    if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && (textLen == 0 || formatBuf.str[0] != '0')) {
1139                        *--formatBuf.str = '0';
1140                        ++textLen;  /* add a zero */
1141                    }
1142                }
1143                break;
1144            default:
1145                break;
1146            }
1147            /*if it's a private arg, just write <priate> to stream*/
1148            if (isPrivacy == 1) {
1149                SecWritePrivateStr(stream, &charsOut);
1150                break;
1151            }
1152
1153            if (noOutput == 0) {
1154                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1155                    if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) {
1156                        /* prefix is a '-' */
1157                        prefix[0] = SECUREC_CHAR('-');
1158                        prefixLen = 1;
1159                    } else if (formatAttr.flags & SECUREC_FLAG_SIGN) {
1160                        /* prefix is '+' */
1161                        prefix[0] = SECUREC_CHAR('+');
1162                        prefixLen = 1;
1163                    } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) {
1164                        /* prefix is ' ' */
1165                        prefix[0] = SECUREC_CHAR(' ');
1166                        prefixLen = 1;
1167                    }
1168                }
1169
1170#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX))
1171                if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (0 == textLen)) {
1172                    formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1173                    formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1];
1174                    *formatBuf.str-- = '\0';
1175                    *formatBuf.str-- = ')';
1176                    *formatBuf.str-- = 'l';
1177                    *formatBuf.str-- = 'i';
1178                    *formatBuf.str-- = 'n';
1179                    *formatBuf.str = '(';
1180                    textLen = 5;
1181                }
1182#endif
1183
1184                /* calculate amount of padding */
1185                padding = (formatAttr.fldWidth - textLen) - prefixLen;
1186
1187                /* put out the padding, prefix, and text, in the correct order */
1188
1189                if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) {
1190                    /* pad on left with blanks */
1191                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1192                        /* char * cast to wchar * */
1193                        SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1194                    } else {
1195                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1196                    }
1197                }
1198
1199                /* write prefix */
1200                if (prefixLen > 0) {
1201                    SecChar *pPrefix = prefix;
1202                    if (SECUREC_IS_REST_BUF_ENOUGH(prefixLen)) {
1203                        /* max prefix len is 2, use loop copy */ /* char * cast to wchar * */
1204                        SECUREC_SAFE_WRITE_PREFIX(pPrefix, prefixLen, stream, &charsOut);
1205                    } else {
1206                        SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut);
1207                    }
1208                }
1209
1210                if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT)
1211                    && padding > 0) {
1212                    /* write leading zeros */
1213                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1214                        /* char * cast to wchar * */
1215                        SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut);
1216                    } else {
1217                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut);
1218                    }
1219                }
1220
1221                /* write text */
1222#ifndef SECUREC_FOR_WCHAR
1223                if (formatAttr.bufferIsWide && (textLen > 0)) {
1224                    wchar_t *p = formatBuf.wStr;
1225                    int count = textLen;
1226                    while (count--) {
1227                        char tmpBuf[SECUREC_MB_LEN + 1];
1228                        SECUREC_MASK_MSVC_CRT_WARNING
1229                        int retVal = wctomb(tmpBuf, *p++);
1230                        SECUREC_END_MASK_MSVC_CRT_WARNING
1231                        if (retVal <= 0) {
1232                            charsOut = -1;
1233                            break;
1234                        }
1235                        SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut);
1236                    }
1237                } else {
1238                    if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1239                        SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut);
1240                    } else {
1241                        SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut);
1242                    }
1243                }
1244#else /* SECUREC_FOR_WCHAR */
1245                if (formatAttr.bufferIsWide == 0 && textLen > 0) {
1246                    int count = textLen;
1247                    char *p = formatBuf.str;
1248
1249                    while (count > 0) {
1250                        wchar_t wchar = L'\0';
1251                        int retVal = mbtowc(&wchar, p, (size_t)MB_CUR_MAX);
1252                        if (retVal <= 0) {
1253                            charsOut = -1;
1254                            break;
1255                        }
1256                        SECUREC_WRITE_CHAR(wchar, stream, &charsOut);
1257                        p += retVal;
1258                        count -= retVal;
1259                    }
1260                } else {
1261                    if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1262                        SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); /* char * cast to wchar * */
1263                    } else {
1264                        SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut);
1265                    }
1266                }
1267#endif /* SECUREC_FOR_WCHAR */
1268
1269                if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) {
1270                    /* pad on right with blanks */
1271                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1272                        /* char * cast to wchar * */
1273                        SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1274                    } else {
1275                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1276                    }
1277                }
1278
1279                /* we're done! */
1280            }
1281            if (floatBuf != NULL) {
1282                SECUREC_FREE(floatBuf);
1283                floatBuf = NULL;
1284            }
1285            break;
1286        case STAT_INVALID:
1287            return -1;
1288        default:
1289            return -1;          /* input format is wrong, directly return */
1290        }
1291    }
1292
1293    if (state != STAT_NORMAL && state != STAT_TYPE) {
1294        return -1;
1295    }
1296
1297    return charsOut;            /* the number of characters written */
1298}                               /* arglist must not be declare as const */
1299#endif /* OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */
1300
1301