• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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'):  [[fallthrough]];
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                [[fallthrough]];
622            case SECUREC_CHAR('c'):
623                {
624                    unsigned int cValue = (unsigned int)va_arg(arglist, int);
625                    /*if it's a private arg, just write <priate> to stream*/
626                    if (isPrivacy == 1) {
627                        break;
628                    }
629                    textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer);
630                    if (textLen < 0) {
631                        noOutput = 1;
632                    }
633                }
634                break;
635            case SECUREC_CHAR('S'):    /* wide char string */
636#ifndef SECUREC_FOR_WCHAR
637                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
638                    formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
639                }
640#else
641                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
642                    formatAttr.flags |= SECUREC_FLAG_SHORT;
643                }
644#endif
645                [[fallthrough]];
646            case SECUREC_CHAR('s'):
647                {
648                    char *argPtr = (char *)va_arg(arglist, char *);
649                    /*if it's a private arg, just write <priate> to stream*/
650                    if (isPrivacy == 1) {
651                        break;
652                    }
653                    textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf);
654                }
655                break;
656
657            case SECUREC_CHAR('n'):
658                /* higher risk disable it */
659                return -1;
660
661            case SECUREC_CHAR('E'):    /* fall-through */ /* FALLTHRU */
662            case SECUREC_CHAR('F'):    /* fall-through */ /* FALLTHRU */
663            case SECUREC_CHAR('G'):    /* fall-through */ /* FALLTHRU */
664            case SECUREC_CHAR('A'):    /* fall-through */ /* FALLTHRU */
665                /* convert format char to lower , use Explicit conversion to clean up compilation warning */
666                ch = (SecChar) (ch + ((SecChar) (SECUREC_CHAR('a')) - (SECUREC_CHAR('A'))));
667                [[fallthrough]];
668            case SECUREC_CHAR('e'):    /* fall-through */ /* FALLTHRU */
669            case SECUREC_CHAR('f'):    /* fall-through */ /* FALLTHRU */
670            case SECUREC_CHAR('g'):    /* fall-through */ /* FALLTHRU */
671            case SECUREC_CHAR('a'):
672                {
673                    /*if it's a private arg, just write <priate> to stream*/
674                    if (isPrivacy == 1) {
675#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
676                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
677                            (void)va_arg(arglist, long double);
678                        } else
679#endif
680                        {
681                            (void)va_arg(arglist, double);
682                        }
683                        break;
684                    }
685
686                    /* floating point conversion */
687                    formatBuf.str = buffer.str; /* output buffer for float string with default size */
688
689                    /* compute the precision value */
690                    if (formatAttr.precision < 0) {
691                        formatAttr.precision = 6;
692                    } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) {
693                        formatAttr.precision = 1;
694                    }
695
696                    /* calc buffer size to store long double value */
697                    if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
698                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) {
699                            noOutput = 1;
700                            break;
701                        }
702                        bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision;
703                    } else {
704                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) {
705                            noOutput = 1;
706                            break;
707                        }
708                        bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision;
709                    }
710                    if (formatAttr.fldWidth > bufferSize) {
711                        bufferSize = formatAttr.fldWidth;
712                    }
713
714                    if (bufferSize >= SECUREC_BUFFER_SIZE) {
715                        /* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */
716                        /* size include '+' and '\0' */
717                        floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2));
718                        if (floatBuf != NULL) {
719                            formatBuf.str = floatBuf;
720                        } else {
721                            noOutput = 1;
722                            break;
723                        }
724                    }
725
726                    {
727                        /* add following code to call system sprintf API for float number */
728                        const SecChar *pFltFmt = format - 2;    /* point to the position before 'f' or 'g' */
729                        int k;
730                        int fltFmtStrLen;
731                        char fltFmtBuf[SECUREC_FMT_STR_LEN];
732                        char *fltFmtStr = fltFmtBuf;
733                        char *fltFmtHeap = NULL;    /* to clear warning */
734
735                        /* must meet '%' (normal format) or '}'(with{private} or{public} format)*/
736                        while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) {
737                            --pFltFmt;
738                        }
739                        fltFmtStrLen = (int)((format - pFltFmt) + 1);   /* with ending terminator */
740                        if (fltFmtStrLen > SECUREC_FMT_STR_LEN) {
741                            /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */
742                            fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen));
743                            if (fltFmtHeap == NULL) {
744                                noOutput = 1;
745                                break;
746                            } else {
747                                fltFmtHeap[0] = '%';
748                                for (k = 1; k < fltFmtStrLen - 1; ++k) {
749                                    /* convert wchar to char */
750                                    fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */
751                                }
752                                fltFmtHeap[k] = '\0';
753
754                                fltFmtStr = fltFmtHeap;
755                            }
756                        } else {
757                            /* purpose of the repeat code is to solve the tool alarm  Redundant_Null_Check */
758                            fltFmtBuf[0] = '%';
759                            for (k = 1; k < fltFmtStrLen - 1; ++k) {
760                                /* convert wchar to char */
761                                fltFmtBuf[k] = (char)(pFltFmt[k]);  /* copy the format string */
762                            }
763                            fltFmtBuf[k] = '\0';
764                        }
765
766#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
767                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
768                            long double tmp = (long double)va_arg(arglist, long double);
769                            /* call system sprintf to format float value */
770                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
771                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
772                                                             formatAttr.fldWidth,formatAttr.precision, tmp);
773                            } else if (formatAttr.dynWidth) {
774                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
775                                                             formatAttr.fldWidth, tmp);
776                            } else if (formatAttr.dynPrecision) {
777                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
778                                                             formatAttr.precision, tmp);
779                            } else {
780                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
781                            }
782                        } else
783#endif
784                        {
785                            double tmp = (double)va_arg(arglist, double);
786                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
787                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
788                                                             formatAttr.precision, tmp);
789                            } else if (formatAttr.dynWidth) {
790                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
791                                                             tmp);
792                            } else if (formatAttr.dynPrecision) {
793                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision,
794                                                             tmp);
795                            } else {
796                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
797                            }
798                        }
799
800                        if (fltFmtHeap != NULL) {
801                            /* if buffer is allocated on heap, free it */
802                            SECUREC_FREE(fltFmtHeap);
803                            fltFmtHeap = NULL;
804                            /* to clear e438 last value assigned not used , the compiler will optimize this code */
805                            (void)fltFmtHeap;
806                        }
807                        if (textLen < 0) {
808                            /* bufferSize is large enough,just validation the return value */
809                            noOutput = 1;
810                            break;
811                        }
812
813                        formatAttr.fldWidth = textLen;  /* no padding ,this variable to calculate amount of padding */
814                        prefixLen = 0;  /* no padding ,this variable to  calculate amount of padding */
815                        formatAttr.flags = 0;   /* clear all internal formatAttr.flags */
816                        break;
817                    }
818                }
819
820            case SECUREC_CHAR('p'):
821                /* print a pointer */
822#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
823                formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
824#else
825                formatAttr.flags |= SECUREC_FLAG_POINTER;
826#endif
827
828#ifdef SECUREC_ON_64BITS
829                formatAttr.flags |= SECUREC_FLAG_I64;   /* converting an int64 */
830#else
831                formatAttr.flags |= SECUREC_FLAG_LONG;  /* converting a long */
832#endif
833
834#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX))
835
836#if defined(SECUREC_VXWORKS_PLATFORM)
837                formatAttr.precision = 1;
838#else
839                formatAttr.precision = 0;
840#endif
841                formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */
842                digits = itoaLowerDigits;
843                goto OUTPUT_HEX;
844#else
845/* not linux vxwoks */
846#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
847                formatAttr.precision = 1;
848#else
849                formatAttr.precision = 2 * sizeof(void *);
850#endif
851
852#endif
853
854#if defined(SECUREC_ON_UNIX)
855                digits = itoaLowerDigits;
856                goto OUTPUT_HEX;
857#endif
858
859                [[fallthrough]];
860            case SECUREC_CHAR('X'):
861                /* unsigned upper hex output */
862                digits = itoaUpperDigits;
863                goto OUTPUT_HEX;
864            case SECUREC_CHAR('x'):
865                /* unsigned lower hex output */
866                digits = itoaLowerDigits;
867
868OUTPUT_HEX:
869                radix = 16;
870                if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
871                    /* alternate form means '0x' prefix */
872                    prefix[0] = SECUREC_CHAR('0');
873                    prefix[1] = (SecChar) (digits[16]); /* 'x' or 'X' */
874
875#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM))
876                    if (ch == 'p') {
877                        prefix[1] = SECUREC_CHAR('x');
878                    }
879#endif
880#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
881                    if (ch == 'p') {
882                        prefixLen = 0;
883                    } else {
884                        prefixLen = 2;
885                    }
886#else
887                    prefixLen = 2;
888#endif
889
890                }
891                goto OUTPUT_INT;
892            case SECUREC_CHAR('i'):    /* fall-through */ /* FALLTHRU */
893            case SECUREC_CHAR('d'):    /* fall-through */ /* FALLTHRU */
894                /* signed decimal output */
895                formatAttr.flags |= SECUREC_FLAG_SIGNED;
896                [[fallthrough]];
897            case SECUREC_CHAR('u'):
898                radix = 10;
899                goto OUTPUT_INT;
900            case SECUREC_CHAR('o'):
901                /* unsigned octal output */
902                radix = 8;
903                if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) {
904                    /* alternate form means force a leading 0 */
905                    formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL;
906                }
907OUTPUT_INT:
908                {
909
910                    SecUnsignedInt64 number = 0;    /* number to convert */
911                    SecInt64 l; /* temp long value */
912                    unsigned char tch;
913#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS)
914                    SecUnsignedInt32 digit = 0; /* ascii value of digit */
915                    SecUnsignedInt32 quotientHigh = 0;
916                    SecUnsignedInt32 quotientLow = 0;
917#endif
918
919                    /* read argument into variable l */
920                    if (formatAttr.flags & SECUREC_FLAG_I64) {
921                        l = (SecInt64)va_arg(arglist, SecInt64);
922                    } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) {
923                        l = (SecInt64)va_arg(arglist, SecInt64);
924                    } else
925#ifdef SECUREC_ON_64BITS
926                    if (formatAttr.flags & SECUREC_FLAG_LONG) {
927                        l = (long)va_arg(arglist, long);
928                    } else
929#endif /* SECUREC_ON_64BITS */
930                    if (formatAttr.flags & SECUREC_FLAG_CHAR) {
931                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
932                            l = (char)va_arg(arglist, int); /* sign extend */
933                            if (l >= 128) { /* on some platform, char is always unsigned */
934                                SecUnsignedInt64 tmpL = (SecUnsignedInt64)l;
935                                formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
936                                tch = (unsigned char)(~(tmpL));
937                                l = tch + 1;
938                            }
939                        } else {
940                            l = (unsigned char)va_arg(arglist, int);    /* zero-extend */
941                        }
942
943                    } else if (formatAttr.flags & SECUREC_FLAG_SHORT) {
944                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
945                            l = (short)va_arg(arglist, int);    /* sign extend */
946                        } else {
947                            l = (unsigned short)va_arg(arglist, int);   /* zero-extend */
948                        }
949
950                    }
951#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
952                    else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) {
953                        l = (ptrdiff_t)va_arg(arglist, ptrdiff_t);  /* sign extend */
954                    } else if (formatAttr.flags & SECUREC_FLAG_SIZE) {
955                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
956                            /* No suitable macros were found to handle the branch */
957                            if (SecIsSameSize(sizeof(size_t), sizeof(long))) {
958                                l = va_arg(arglist, long);  /* sign extend */
959                            } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) {
960                                l = va_arg(arglist, long long); /* sign extend */
961                            } else {
962                                l = va_arg(arglist, int);   /* sign extend */
963                            }
964                        } else {
965                            l = (SecInt64)(size_t)va_arg(arglist, size_t);  /* sign extend */
966                        }
967                    } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) {
968                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
969                            l = va_arg(arglist, SecInt64);  /* sign extend */
970                        } else {
971                            l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64);  /* sign extend */
972                        }
973                    }
974#endif
975                    else {
976                        if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
977                            l = va_arg(arglist, int);   /* sign extend */
978                        } else {
979                            l = (unsigned int)va_arg(arglist, int); /* zero-extend */
980                        }
981
982                    }
983                    /*if it's a private arg, just write <priate> to stream*/
984                    if (isPrivacy == 1) {
985                        break;
986                    }
987
988                    /* check for negative; copy into number */
989                    if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) {
990                        number = (SecUnsignedInt64)(-l);
991                        formatAttr.flags |= SECUREC_FLAG_NEGATIVE;
992                    } else {
993                        number = (SecUnsignedInt64)l;
994                    }
995
996                    if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) &&
997#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
998                        ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) &&
999#endif
1000#ifdef SECUREC_ON_64BITS
1001                        ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) &&
1002                        ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) &&
1003#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT)  /* on window 64 system sizeof long is 32bit */
1004                        ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) &&
1005#endif
1006#endif
1007                        ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) {
1008
1009                            number &= 0xffffffff;
1010                    }
1011
1012                    /* check precision value for default */
1013                    if (formatAttr.precision < 0) {
1014                        formatAttr.precision = 1;   /* default precision */
1015                    } else {
1016#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
1017                        formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1018#else
1019                        if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) {
1020                            formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1021                        }
1022#endif
1023                        if (formatAttr.precision > SECUREC_MAX_PRECISION) {
1024                            formatAttr.precision = SECUREC_MAX_PRECISION;
1025                        }
1026                    }
1027
1028                    /* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */
1029                    if (number == 0) {
1030#if !(defined(SECUREC_VXWORKS_PLATFORM)||defined(__hpux))
1031                        prefixLen = 0;
1032#else
1033                        if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE))
1034                            prefixLen = 2;
1035                        else
1036                            prefixLen = 0;
1037#endif
1038                    }
1039
1040                    /* Convert data to ASCII */
1041                    formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE];
1042
1043                    if (number > 0) {
1044#ifdef SECUREC_ON_64BITS
1045                        switch (radix) {
1046                            /* the compiler will optimize each one */
1047                            SECUREC_SPECIAL(number, 10);
1048                            break;
1049                            SECUREC_SPECIAL(number, 16);
1050                            break;
1051                            SECUREC_SPECIAL(number, 8);
1052                            break;
1053                        default:
1054                            break;
1055                        }
1056#else /* for 32 bits system */
1057                        if (number <= 0xFFFFFFFFUL) {
1058                            /* in most case, the value to be converted is small value */
1059                            SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number;
1060                            switch (radix) {
1061                                SECUREC_SPECIAL(n32Tmp, 16);
1062                                break;
1063                                SECUREC_SPECIAL(n32Tmp, 8);
1064                                break;
1065
1066#ifdef _AIX
1067                                /* the compiler will optimize div 10 */
1068                                SECUREC_SPECIAL(n32Tmp, 10);
1069                                break;
1070#else
1071                            case 10:
1072                                {
1073                                    /* fast div 10 */
1074                                    SecUnsignedInt32 q;
1075                                    SecUnsignedInt32 r;
1076                                    do {
1077                                        *--formatBuf.str = digits[n32Tmp % 10];
1078                                        q = (n32Tmp >> 1) + (n32Tmp >> 2);
1079                                        q = q + (q >> 4);
1080                                        q = q + (q >> 8);
1081                                        q = q + (q >> 16);
1082                                        q = q >> 3;
1083                                        r = n32Tmp - (((q << 2) + q) << 1);
1084                                        n32Tmp = (r > 9) ? (q + 1) : q;
1085                                    } while (n32Tmp != 0);
1086                                }
1087                                break;
1088#endif
1089                            default:
1090                                break;
1091                            }   /* end switch */
1092                        } else {
1093                            /* the value to be converted is greater than 4G */
1094#if defined(SECUREC_VXWORKS_VERSION_5_4)
1095                            do {
1096                                if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16),
1097                                                     (SecUnsignedInt32)number,
1098                                                     (SecUnsignedInt32)radix, &quotientHigh, &quotientLow, &digit)) {
1099                                    noOutput = 1;
1100                                    break;
1101                                }
1102                                *--formatBuf.str = digits[digit];
1103
1104                                number = (SecUnsignedInt64)quotientHigh;
1105                                number = (number << 32) + quotientLow;
1106                            } while (number != 0);
1107#else
1108                            switch (radix) {
1109                                /* the compiler will optimize div 10 */
1110                                SECUREC_SPECIAL(number, 10);
1111                                break;
1112                                SECUREC_SPECIAL(number, 16);
1113                                break;
1114                                SECUREC_SPECIAL(number, 8);
1115                                break;
1116                            default:
1117                                break;
1118                            }
1119#endif
1120                        }
1121#endif
1122                    }           /* END if (number > 0) */
1123                    /* compute length of number,.if textLen > 0, then formatBuf.str must be in buffer.str */
1124                    textLen = (int)((char *)&buffer.str[SECUREC_BUFFER_SIZE] - formatBuf.str);
1125                    if (formatAttr.precision > textLen) {
1126                        for (ii = 0; ii < formatAttr.precision - textLen; ++ii) {
1127                            *--formatBuf.str = '0';
1128                        }
1129                        textLen = formatAttr.precision;
1130                    }
1131
1132                    /* Force a leading zero if FORCEOCTAL flag set */
1133                    if ((formatAttr.flags & SECUREC_FLAG_FORCE_OCTAL) && (textLen == 0 || formatBuf.str[0] != '0')) {
1134                        *--formatBuf.str = '0';
1135                        ++textLen;  /* add a zero */
1136                    }
1137                }
1138                break;
1139            default:
1140                break;
1141            }
1142            /*if it's a private arg, just write <priate> to stream*/
1143            if (isPrivacy == 1) {
1144                SecWritePrivateStr(stream, &charsOut);
1145                break;
1146            }
1147
1148            if (noOutput == 0) {
1149                if (formatAttr.flags & SECUREC_FLAG_SIGNED) {
1150                    if (formatAttr.flags & SECUREC_FLAG_NEGATIVE) {
1151                        /* prefix is a '-' */
1152                        prefix[0] = SECUREC_CHAR('-');
1153                        prefixLen = 1;
1154                    } else if (formatAttr.flags & SECUREC_FLAG_SIGN) {
1155                        /* prefix is '+' */
1156                        prefix[0] = SECUREC_CHAR('+');
1157                        prefixLen = 1;
1158                    } else if (formatAttr.flags & SECUREC_FLAG_SIGN_SPACE) {
1159                        /* prefix is ' ' */
1160                        prefix[0] = SECUREC_CHAR(' ');
1161                        prefixLen = 1;
1162                    }
1163                }
1164
1165#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) && (!defined(SECUREC_ON_UNIX))
1166                if ((formatAttr.flags & SECUREC_FLAG_POINTER) && (0 == textLen)) {
1167                    formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
1168                    formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE - 1];
1169                    *formatBuf.str-- = '\0';
1170                    *formatBuf.str-- = ')';
1171                    *formatBuf.str-- = 'l';
1172                    *formatBuf.str-- = 'i';
1173                    *formatBuf.str-- = 'n';
1174                    *formatBuf.str = '(';
1175                    textLen = 5;
1176                }
1177#endif
1178
1179                /* calculate amount of padding */
1180                padding = (formatAttr.fldWidth - textLen) - prefixLen;
1181
1182                /* put out the padding, prefix, and text, in the correct order */
1183
1184                if (!(formatAttr.flags & (SECUREC_FLAG_LEFT | SECUREC_FLAG_LEADZERO)) && padding > 0) {
1185                    /* pad on left with blanks */
1186                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1187                        /* char * cast to wchar * */
1188                        SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1189                    } else {
1190                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1191                    }
1192                }
1193
1194                /* write prefix */
1195                if (prefixLen > 0) {
1196                    SecChar *pPrefix = prefix;
1197                    if (SECUREC_IS_REST_BUF_ENOUGH(prefixLen)) {
1198                        /* max prefix len is 2, use loop copy */ /* char * cast to wchar * */
1199                        SECUREC_SAFE_WRITE_PREFIX(pPrefix, prefixLen, stream, &charsOut);
1200                    } else {
1201                        SECUREC_WRITE_STRING(prefix, prefixLen, stream, &charsOut);
1202                    }
1203                }
1204
1205                if ((formatAttr.flags & SECUREC_FLAG_LEADZERO) && !(formatAttr.flags & SECUREC_FLAG_LEFT)
1206                    && padding > 0) {
1207                    /* write leading zeros */
1208                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1209                        /* char * cast to wchar * */
1210                        SECUREC_SAFE_PADDING(SECUREC_CHAR('0'), padding, stream, &charsOut);
1211                    } else {
1212                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR('0'), padding, stream, &charsOut);
1213                    }
1214                }
1215
1216                /* write text */
1217#ifndef SECUREC_FOR_WCHAR
1218                if (formatAttr.bufferIsWide && (textLen > 0)) {
1219                    wchar_t *p = formatBuf.wStr;
1220                    int count = textLen;
1221                    while (count--) {
1222                        char tmpBuf[SECUREC_MB_LEN + 1];
1223                        SECUREC_MASK_MSVC_CRT_WARNING
1224                        int retVal = wctomb(tmpBuf, *p++);
1225                        SECUREC_END_MASK_MSVC_CRT_WARNING
1226                        if (retVal <= 0) {
1227                            charsOut = -1;
1228                            break;
1229                        }
1230                        SECUREC_WRITE_STRING(tmpBuf, retVal, stream, &charsOut);
1231                    }
1232                } else {
1233                    if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1234                        SECUREC_SAFE_WRITE_STR(formatBuf.str, textLen, stream, &charsOut);
1235                    } else {
1236                        SECUREC_WRITE_STRING(formatBuf.str, textLen, stream, &charsOut);
1237                    }
1238                }
1239#else /* SECUREC_FOR_WCHAR */
1240                if (formatAttr.bufferIsWide == 0 && textLen > 0) {
1241                    int count = textLen;
1242                    char *p = formatBuf.str;
1243
1244                    while (count > 0) {
1245                        wchar_t wchar = L'\0';
1246                        int retVal = mbtowc(&wchar, p, (size_t)MB_CUR_MAX);
1247                        if (retVal <= 0) {
1248                            charsOut = -1;
1249                            break;
1250                        }
1251                        SECUREC_WRITE_CHAR(wchar, stream, &charsOut);
1252                        p += retVal;
1253                        count -= retVal;
1254                    }
1255                } else {
1256                    if (SECUREC_IS_REST_BUF_ENOUGH(textLen)) {
1257                        SECUREC_SAFE_WRITE_STR(formatBuf.wStr, textLen, stream, &charsOut); /* char * cast to wchar * */
1258                    } else {
1259                        SECUREC_WRITE_STRING(formatBuf.wStr, textLen, stream, &charsOut);
1260                    }
1261                }
1262#endif /* SECUREC_FOR_WCHAR */
1263
1264                if (charsOut >= 0 && (formatAttr.flags & SECUREC_FLAG_LEFT) && padding > 0) {
1265                    /* pad on right with blanks */
1266                    if (SECUREC_IS_REST_BUF_ENOUGH(padding)) {
1267                        /* char * cast to wchar * */
1268                        SECUREC_SAFE_PADDING(SECUREC_CHAR(' '), padding, stream, &charsOut);
1269                    } else {
1270                        SECUREC_WRITE_MULTI_CHAR(SECUREC_CHAR(' '), padding, stream, &charsOut);
1271                    }
1272                }
1273
1274                /* we're done! */
1275            }
1276            if (floatBuf != NULL) {
1277                SECUREC_FREE(floatBuf);
1278                floatBuf = NULL;
1279            }
1280            break;
1281        case STAT_INVALID:
1282            return -1;
1283        default:
1284            return -1;          /* input format is wrong, directly return */
1285        }
1286    }
1287
1288    if (state != STAT_NORMAL && state != STAT_TYPE) {
1289        return -1;
1290    }
1291
1292    return charsOut;            /* the number of characters written */
1293}                               /* arglist must not be declare as const */
1294#endif /* OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 */
1295
1296