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, "ientHigh, "ientLow, &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