• 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'):    /* fall-through */ /* FALLTHRU */
212    case SECUREC_CHAR('L'):
213        attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE;
214        break;
215    case SECUREC_CHAR('l'):
216        if (**format == SECUREC_CHAR('l')) {
217            ++(*format);
218            attr->flags |= SECUREC_FLAG_LONGLONG;   /* long long */
219        } else {
220            attr->flags |= SECUREC_FLAG_LONG;   /* long int or wchar_t */
221        }
222        break;
223    case SECUREC_CHAR('t'):
224        attr->flags |= SECUREC_FLAG_PTRDIFF;
225        break;
226#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
227    case SECUREC_CHAR('z'):
228        attr->flags |= SECUREC_FLAG_SIZE;
229        break;
230    case SECUREC_CHAR('Z'):
231        attr->flags |= SECUREC_FLAG_SIZE;
232        break;
233#endif
234
235    case SECUREC_CHAR('I'):
236#ifdef SECUREC_ON_64BITS
237        attr->flags |= SECUREC_FLAG_I64;    /* %I  to  INT64 */
238#endif
239        if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) {
240            (*format) += 2;
241            attr->flags |= SECUREC_FLAG_I64;    /* %I64  to  INT64 */
242        } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) {
243            (*format) += 2;
244            attr->flags &= ~SECUREC_FLAG_I64;   /* %I64  to  INT32 */
245        } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) ||
246                   (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) ||
247                   (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) {
248            /* do nothing */
249        } else {
250            /* Compatibility  code for "%I" just print I */
251            return -1;
252        }
253        break;
254
255    case SECUREC_CHAR('h'):
256        if (**format == SECUREC_CHAR('h'))
257            attr->flags |= SECUREC_FLAG_CHAR;   /* char */
258        else
259            attr->flags |= SECUREC_FLAG_SHORT;  /* short int */
260        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
403int SecOutputPS(SecPrintfStream *stream, int priv, const char *cformat, va_list arglist)
404{
405    const SecChar *format = cformat;
406
407    char *floatBuf = NULL;
408    SecFormatBuf formatBuf;
409    static const char *itoaUpperDigits = "0123456789ABCDEFX";
410    static const char *itoaLowerDigits = "0123456789abcdefx";
411    const char *digits = itoaUpperDigits;
412    int ii = 0;
413
414    unsigned int radix;
415    int charsOut;               /* characters written */
416
417    int prefixLen = 0;
418    int padding = 0;
419
420    int textLen;                /* length of the text */
421    int bufferSize = 0;         /* size of formatBuf.str */
422    int noOutput = 0;
423
424    SecFmtState state;
425    SecFmtState laststate;
426
427    SecChar prefix[2] = { 0 };
428    SecChar ch;                 /* currently read character */
429
430    static const unsigned char fmtCharTable[337] = {
431        /* type 0:    nospecial meaning;
432           1:   '%';
433           2:    '.'
434           3:    '*'
435           4:    '0'
436           5:    '1' ... '9'
437           6:    ' ', '+', '-', '#'
438           7:     'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j'
439           8:     'd','o','u','i','x','X','e','f','g'
440         */
441        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
443        0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00,
444        0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445        0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00,
446        0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
447        0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08,
448        0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
449        /* fill zero  for normal char 128 byte for 0x80 - 0xff */
450        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
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        /* state  0: normal
459           1: percent
460           2: flag
461           3: width
462           4: dot
463           5: precis
464           6: size
465           7: type
466           8: invalid
467         */
468        0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08,
469        0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05,
470        0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03,
471        0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
472        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00,
473        0x00
474    };
475
476    SecFormatAttr formatAttr;
477    SecBuffer buffer;
478    formatAttr.flags = 0;
479    formatAttr.bufferIsWide = 0;    /* flag for buffer contains wide chars */
480    formatAttr.fldWidth = 0;
481    formatAttr.precision = 0;
482    formatAttr.dynWidth = 0;
483    formatAttr.dynPrecision = 0;
484
485    charsOut = 0;
486    textLen = 0;
487    state = STAT_NORMAL;        /* starting state */
488    formatBuf.str = NULL;
489
490    int isPrivacy = 1; /*whether show private string*/
491
492    /* loop each format character */
493    /* remove format != NULL */
494    while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) {
495        laststate = state;
496        state = SECUREC_DECODE_STATE(ch, fmtCharTable, laststate);
497
498        switch (state) {
499        case STAT_NORMAL:
500
501NORMAL_CHAR:
502
503            /* normal state, write character */
504            if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */ )) {
505                SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */
506            } else {
507#ifdef SECUREC_FOR_WCHAR
508                SECUREC_WRITE_CHAR(ch, stream, &charsOut);
509#else
510                /* optimize function call to code */
511                charsOut = -1;
512                stream->count = -1;
513#endif
514            }
515
516            continue;
517
518        case STAT_PERCENT:
519            /* set default values */
520            prefixLen = 0;
521            noOutput = 0;
522            formatAttr.flags = 0;
523            formatAttr.fldWidth = 0;
524            formatAttr.precision = -1;
525            formatAttr.bufferIsWide = 0;
526            if (*format == SECUREC_CHAR('{')) {
527                if (strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN) == 0) {
528                    isPrivacy = 0;
529                    format += PUBLIC_FLAG_LEN;
530                }
531                else if (strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN) == 0) {
532                    isPrivacy = 1;
533                    format += PRIVATE_FLAG_LEN;
534                }
535            }
536            else {
537                isPrivacy = 1;
538            }
539
540            if (0 == priv) {
541                isPrivacy = 0;
542            }
543
544            break;
545
546        case STAT_FLAG:
547            /* set flag based on which flag character */
548            SecDecodeFlags(ch, &formatAttr);
549            break;
550
551        case STAT_WIDTH:
552            /* update width value */
553            if (ch == SECUREC_CHAR('*')) {
554                /* get width */
555                formatAttr.fldWidth = (int)va_arg(arglist, int);
556                if (formatAttr.fldWidth < 0) {
557                    formatAttr.flags |= SECUREC_FLAG_LEFT;
558                    formatAttr.fldWidth = -formatAttr.fldWidth;
559                }
560                formatAttr.dynWidth = 1;
561            } else {
562                if (laststate != STAT_WIDTH) {
563                    formatAttr.fldWidth = 0;
564                }
565                if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) {
566                    return -1;
567                }
568                formatAttr.fldWidth = (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0'));
569                formatAttr.dynWidth = 0;
570            }
571            break;
572
573        case STAT_DOT:
574            formatAttr.precision = 0;
575            break;
576
577        case STAT_PRECIS:
578            /* update precision value */
579            if (ch == SECUREC_CHAR('*')) {
580                /* get precision from arg list */
581                formatAttr.precision = (int)va_arg(arglist, int);
582                if (formatAttr.precision < 0) {
583                    formatAttr.precision = -1;
584                }
585                formatAttr.dynPrecision = 1;
586            } else {
587                /* add digit to current precision */
588                if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) {
589                    return -1;
590                }
591                formatAttr.precision =
592                    (int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0'));
593                formatAttr.dynPrecision = 0;
594            }
595            break;
596
597        case STAT_SIZE:
598            /* read a size specifier, set the formatAttr.flags based on it */
599            if (SecDecodeSize(ch, &formatAttr, &format) != 0) {
600                /* Compatibility  code for "%I" just print I */
601                state = STAT_NORMAL;
602                goto NORMAL_CHAR;
603            }
604            break;
605
606        case STAT_TYPE:
607
608            switch (ch) {
609
610            case SECUREC_CHAR('C'):
611                /* wide char */
612                if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) {
613
614#ifdef SECUREC_FOR_WCHAR
615                    formatAttr.flags |= SECUREC_FLAG_SHORT;
616#else
617                    formatAttr.flags |= SECUREC_FLAG_WIDECHAR;
618#endif
619                }
620                /* fall-through */
621                /* FALLTHRU */
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                /* fall-through */
646                /* FALLTHRU */
647            case SECUREC_CHAR('s'):
648                {
649                    char *argPtr = (char *)va_arg(arglist, char *);
650                    /*if it's a private arg, just write <priate> to stream*/
651                    if (isPrivacy == 1) {
652                        break;
653                    }
654                    textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf);
655                }
656                break;
657
658            case SECUREC_CHAR('n'):
659                /* higher risk disable it */
660                return -1;
661
662            case SECUREC_CHAR('E'):    /* fall-through */ /* FALLTHRU */
663            case SECUREC_CHAR('F'):    /* fall-through */ /* FALLTHRU */
664            case SECUREC_CHAR('G'):    /* fall-through */ /* FALLTHRU */
665            case SECUREC_CHAR('A'):    /* fall-through */ /* FALLTHRU */
666                /* convert format char to lower , use Explicit conversion to clean up compilation warning */
667                ch = (SecChar) (ch + ((SecChar) (SECUREC_CHAR('a')) - (SECUREC_CHAR('A'))));
668                /* fall-through */
669                /* FALLTHRU */
670            case SECUREC_CHAR('e'):    /* fall-through */ /* FALLTHRU */
671            case SECUREC_CHAR('f'):    /* fall-through */ /* FALLTHRU */
672            case SECUREC_CHAR('g'):    /* fall-through */ /* FALLTHRU */
673            case SECUREC_CHAR('a'):
674                {
675                    /*if it's a private arg, just write <priate> to stream*/
676                    if (isPrivacy == 1) {
677#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
678                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
679                            (void)va_arg(arglist, long double);
680                        } else
681#endif
682                        {
683                            (void)va_arg(arglist, double);
684                        }
685                        break;
686                    }
687
688                    /* floating point conversion */
689                    formatBuf.str = buffer.str; /* output buffer for float string with default size */
690
691                    /* compute the precision value */
692                    if (formatAttr.precision < 0) {
693                        formatAttr.precision = 6;
694                    } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) {
695                        formatAttr.precision = 1;
696                    }
697
698                    /* calc buffer size to store long double value */
699                    if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
700                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) {
701                            noOutput = 1;
702                            break;
703                        }
704                        bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision;
705                    } else {
706                        if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) {
707                            noOutput = 1;
708                            break;
709                        }
710                        bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision;
711                    }
712                    if (formatAttr.fldWidth > bufferSize) {
713                        bufferSize = formatAttr.fldWidth;
714                    }
715
716                    if (bufferSize >= SECUREC_BUFFER_SIZE) {
717                        /* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */
718                        /* size include '+' and '\0' */
719                        floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2));
720                        if (floatBuf != NULL) {
721                            formatBuf.str = floatBuf;
722                        } else {
723                            noOutput = 1;
724                            break;
725                        }
726                    }
727
728                    {
729                        /* add following code to call system sprintf API for float number */
730                        const SecChar *pFltFmt = format - 2;    /* point to the position before 'f' or 'g' */
731                        int k;
732                        int fltFmtStrLen;
733                        char fltFmtBuf[SECUREC_FMT_STR_LEN];
734                        char *fltFmtStr = fltFmtBuf;
735                        char *fltFmtHeap = NULL;    /* to clear warning */
736
737                        /* must meet '%' (normal format) or '}'(with{private} or{public} format)*/
738                        while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) {
739                            --pFltFmt;
740                        }
741                        fltFmtStrLen = (int)((format - pFltFmt) + 1);   /* with ending terminator */
742                        if (fltFmtStrLen > SECUREC_FMT_STR_LEN) {
743                            /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */
744                            fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen));
745                            if (fltFmtHeap == NULL) {
746                                noOutput = 1;
747                                break;
748                            } else {
749                                fltFmtHeap[0] = '%';
750                                for (k = 1; k < fltFmtStrLen - 1; ++k) {
751                                    /* convert wchar to char */
752                                    fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */
753                                }
754                                fltFmtHeap[k] = '\0';
755
756                                fltFmtStr = fltFmtHeap;
757                            }
758                        } else {
759                            /* purpose of the repeat code is to solve the tool alarm  Redundant_Null_Check */
760                            fltFmtBuf[0] = '%';
761                            for (k = 1; k < fltFmtStrLen - 1; ++k) {
762                                /* convert wchar to char */
763                                fltFmtBuf[k] = (char)(pFltFmt[k]);  /* copy the format string */
764                            }
765                            fltFmtBuf[k] = '\0';
766                        }
767
768#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT
769                        if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) {
770                            long double tmp = (long double)va_arg(arglist, long double);
771                            /* call system sprintf to format float value */
772                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
773                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
774                                                             formatAttr.fldWidth,formatAttr.precision, tmp);
775                            } else if (formatAttr.dynWidth) {
776                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
777                                                             formatAttr.fldWidth, tmp);
778                            } else if (formatAttr.dynPrecision) {
779                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr,
780                                                             formatAttr.precision, tmp);
781                            } else {
782                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
783                            }
784                        } else
785#endif
786                        {
787                            double tmp = (double)va_arg(arglist, double);
788                            if (formatAttr.dynWidth && formatAttr.dynPrecision) {
789                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
790                                                             formatAttr.precision, tmp);
791                            } else if (formatAttr.dynWidth) {
792                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth,
793                                                             tmp);
794                            } else if (formatAttr.dynPrecision) {
795                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision,
796                                                             tmp);
797                            } else {
798                                textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp);
799                            }
800                        }
801
802                        if (fltFmtHeap != NULL) {
803                            /* if buffer is allocated on heap, free it */
804                            SECUREC_FREE(fltFmtHeap);
805                            fltFmtHeap = NULL;
806                            /* to clear e438 last value assigned not used , the compiler will optimize this code */
807                            (void)fltFmtHeap;
808                        }
809                        if (textLen < 0) {
810                            /* bufferSize is large enough,just validation the return value */
811                            noOutput = 1;
812                            break;
813                        }
814
815                        formatAttr.fldWidth = textLen;  /* no padding ,this variable to calculate amount of padding */
816                        prefixLen = 0;  /* no padding ,this variable to  calculate amount of padding */
817                        formatAttr.flags = 0;   /* clear all internal formatAttr.flags */
818                        break;
819                    }
820                }
821
822            case SECUREC_CHAR('p'):
823                /* print a pointer */
824#if defined(SECUREC_COMPATIBLE_WIN_FORMAT)
825                formatAttr.flags &= ~SECUREC_FLAG_LEADZERO;
826#else
827                formatAttr.flags |= SECUREC_FLAG_POINTER;
828#endif
829
830#ifdef SECUREC_ON_64BITS
831                formatAttr.flags |= SECUREC_FLAG_I64;   /* converting an int64 */
832#else
833                formatAttr.flags |= SECUREC_FLAG_LONG;  /* converting a long */
834#endif
835
836#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX))
837
838#if defined(SECUREC_VXWORKS_PLATFORM)
839                formatAttr.precision = 1;
840#else
841                formatAttr.precision = 0;
842#endif
843                formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */
844                digits = itoaLowerDigits;
845                goto OUTPUT_HEX;
846#else
847/* not linux vxwoks */
848#if defined(_AIX) || defined(SECUREC_ON_SOLARIS)
849                formatAttr.precision = 1;
850#else
851                formatAttr.precision = 2 * sizeof(void *);
852#endif
853
854#endif
855
856#if defined(SECUREC_ON_UNIX)
857                digits = itoaLowerDigits;
858                goto OUTPUT_HEX;
859#endif
860
861                /* fall-through */
862                /* FALLTHRU */
863            case SECUREC_CHAR('X'):
864                /* unsigned upper hex output */
865                digits = itoaUpperDigits;
866                goto OUTPUT_HEX;
867
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