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