1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 17/* [Standardize-exceptions] Use unsafe function: Portability 18 * [reason] Use unsafe function to implement security function to maintain platform compatibility. 19 * And sufficient input validation is performed before calling 20 */ 21 22#ifndef OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 23#define OUTPUT_P_INL_2B263E9C_43D8_44BB_B17A_6D2033DECEE5 24 25#define SECUREC_FLOAT_BUFSIZE (309+40) /* max float point value */ 26#define SECUREC_FLOAT_BUFSIZE_LB (4932+40) /* max long double value */ 27 28#define SECUREC_INT_MAX 2147483647 29 30#define SECUREC_MUL10(x) ((((x) << 2) + (x)) << 1) 31#define SECUREC_INT_MAX_DIV_TEN 21474836 32#define SECUREC_MUL10_ADD_BEYOND_MAX(val) (((val) > SECUREC_INT_MAX_DIV_TEN)) 33 34#ifdef SECUREC_STACK_SIZE_LESS_THAN_1K 35#define SECUREC_FMT_STR_LEN (8) 36#else 37#define SECUREC_FMT_STR_LEN (16) 38#endif 39 40typedef struct { 41 unsigned int flags; 42 int fldWidth; 43 int precision; 44 int bufferIsWide; /* flag for buffer contains wide chars */ 45 int dynWidth; /* %* 1 width from variable parameter ;0 not */ 46 int dynPrecision; /* %.* 1 precision from variable parameter ;0 not */ 47} SecFormatAttr; 48 49typedef union { 50 char *str; /* not a null terminated string */ 51 wchar_t *wStr; 52} SecFormatBuf; 53 54typedef union { 55 char str[SECUREC_BUFFER_SIZE + 1]; 56#ifdef SECUREC_FOR_WCHAR 57 wchar_t wStr[SECUREC_BUFFER_SIZE + 1]; 58#endif 59} SecBuffer; 60 61static int SecIndirectSprintf(char *strDest, const char *format, ...) 62{ 63 int ret; /* If initialization causes e838 */ 64 va_list arglist; 65 66 va_start(arglist, format); 67 SECUREC_MASK_MSVC_CRT_WARNING 68 ret = vsprintf(strDest, format, arglist); 69 SECUREC_END_MASK_MSVC_CRT_WARNING 70 va_end(arglist); 71 (void)arglist; /* to clear e438 last value assigned not used , the compiler will optimize this code */ 72 73 return ret; 74} 75 76#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 77/* to clear e506 warning */ 78static int SecIsSameSize(size_t sizeA, size_t sizeB) 79{ 80 return sizeA == sizeB; 81} 82#endif 83 84#define SECUREC_SPECIAL(_val, Base) \ 85 case Base: \ 86 do { \ 87 *--formatBuf.str = digits[_val % Base]; \ 88 }while ((_val /= Base) != 0) 89 90#define SECUREC_SAFE_WRITE_PREFIX(src, txtLen, _stream, outChars) do { \ 91 for (ii = 0; ii < txtLen; ++ii) { \ 92 *((SecChar *)(void *)(_stream->cur)) = *(src); \ 93 _stream->cur += sizeof(SecChar); \ 94 ++(src); \ 95 } \ 96 _stream->count -= txtLen * (int)(sizeof(SecChar)); \ 97 *(outChars) = *(outChars) + (txtLen); \ 98 } SECUREC_WHILE_ZERO 99 100#define SECUREC_SAFE_WRITE_STR(src, txtLen, _stream, outChars) do { \ 101 if (txtLen < 12 /* for mobile number length */) { \ 102 for (ii = 0; ii < txtLen; ++ii) { \ 103 *((SecChar *)(void *)(_stream->cur)) = *(src); \ 104 _stream->cur += sizeof(SecChar); \ 105 ++(src); \ 106 } \ 107 } else { \ 108 (void)memcpy(_stream->cur, src, ((size_t)(unsigned int)txtLen * (sizeof(SecChar)))); \ 109 _stream->cur += (size_t)(unsigned int)txtLen * (sizeof(SecChar)); \ 110 } \ 111 _stream->count -= txtLen * (int)(sizeof(SecChar)); \ 112 *(outChars) = *(outChars) + (txtLen); \ 113 } SECUREC_WHILE_ZERO 114 115#define SECUREC_SAFE_WRITE_CHAR(_ch, _stream, outChars) do { \ 116 *((SecChar *)(void *)(_stream->cur)) = (SecChar)_ch; \ 117 _stream->cur += sizeof(SecChar); \ 118 _stream->count -= (int)(sizeof(SecChar)); \ 119 *(outChars) = *(outChars) + 1; \ 120 } SECUREC_WHILE_ZERO 121 122#define SECUREC_SAFE_PADDING(padChar, padLen, _stream, outChars) do { \ 123 for (ii = 0; ii < padLen; ++ii) { \ 124 *((SecChar *)(void *)(_stream->cur)) = (SecChar)padChar; \ 125 _stream->cur += sizeof(SecChar); \ 126 } \ 127 _stream->count -= padLen * (int)(sizeof(SecChar)); \ 128 *(outChars) = *(outChars) + (padLen); \ 129 } SECUREC_WHILE_ZERO 130 131/* The count variable can be reduced to 0, and the external function complements the \0 terminator. */ 132#define SECUREC_IS_REST_BUF_ENOUGH(needLen) ((int)(stream->count - (int)needLen * (int)(sizeof(SecChar))) >= 0) 133 134#define SECUREC_FMT_STATE_OFFSET 256 135#ifdef SECUREC_FOR_WCHAR 136#define SECUREC_FMT_TYPE(c,fmtTable) ((((unsigned int)(int)(c)) <= (unsigned int)(int)SECUREC_CHAR('~')) ? \ 137 (fmtTable[(unsigned char)(c)]) : 0) 138#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)(((fmtTable[(SECUREC_FMT_TYPE(c,fmtTable)) * \ 139 ((unsigned char)STAT_INVALID + 1) + \ 140 (unsigned char)(laststate) + \ 141 SECUREC_FMT_STATE_OFFSET]))) 142#else 143#define SECUREC_DECODE_STATE(c,fmtTable,laststate) (SecFmtState)((fmtTable[(fmtTable[(unsigned char)(c)]) * \ 144 ((unsigned char)STAT_INVALID + 1) + \ 145 (unsigned char)(laststate) + \ 146 SECUREC_FMT_STATE_OFFSET])) 147#endif 148 149#define PUBLIC_FLAG_LEN 8 150#define PRIVATE_FLAG_LEN 9 151#define PUBLIC_FLAG "{public}" 152#define PRIVATE_FLAG "{private}" 153 154static void SecWritePrivateStr(SecPrintfStream *stream, int *pCharsOut) 155{ 156 int ii = 0; 157#define PRIVATE_STR_LEN (9) 158#ifndef SECUREC_FOR_WCHAR 159 static const char privacyString[] = "<private>"; 160 const char *pPrivStr = privacyString; 161 162 if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) { 163 SECUREC_SAFE_WRITE_STR(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 164 } else { 165 SECUREC_WRITE_STRING(pPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 166 } 167#else 168 static const wchar_t wprivacyString[] = { L'<', L'p', L'r', L'i', L'v', L'a', L't', L'e', L'>', L'\0' }; 169 const wchar_t *pwPrivStr = wprivacyString; 170 171 if (SECUREC_IS_REST_BUF_ENOUGH(PRIVATE_STR_LEN)) { 172 SECUREC_SAFE_WRITE_STR(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 173 } else { 174 SECUREC_WRITE_STRING(pwPrivStr, PRIVATE_STR_LEN, stream, pCharsOut); 175 } 176#endif 177} 178 179static void SecDecodeFlags(SecChar ch, SecFormatAttr *attr) 180{ 181 switch (ch) { 182 case SECUREC_CHAR(' '): 183 attr->flags |= SECUREC_FLAG_SIGN_SPACE; 184 break; 185 case SECUREC_CHAR('+'): 186 attr->flags |= SECUREC_FLAG_SIGN; 187 break; 188 case SECUREC_CHAR('-'): 189 attr->flags |= SECUREC_FLAG_LEFT; 190 break; 191 case SECUREC_CHAR('0'): 192 attr->flags |= SECUREC_FLAG_LEADZERO; /* add zero th the front */ 193 break; 194 case SECUREC_CHAR('#'): 195 attr->flags |= SECUREC_FLAG_ALTERNATE; /* output %x with 0x */ 196 break; 197 default: 198 break; 199 } 200 return; 201} 202 203static int SecDecodeSize(SecChar ch, SecFormatAttr *attr, const SecChar **format) 204{ 205 switch (ch) { 206#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 207 case SECUREC_CHAR('j'): 208 attr->flags |= SECUREC_FLAG_INTMAX; 209 break; 210#endif 211 case SECUREC_CHAR('q'): 212 case SECUREC_CHAR('L'): 213 attr->flags |= SECUREC_FLAG_LONGLONG | SECUREC_FLAG_LONG_DOUBLE; 214 break; 215 case SECUREC_CHAR('l'): 216 if (**format == SECUREC_CHAR('l')) { 217 ++(*format); 218 attr->flags |= SECUREC_FLAG_LONGLONG; /* long long */ 219 } else { 220 attr->flags |= SECUREC_FLAG_LONG; /* long int or wchar_t */ 221 } 222 break; 223 case SECUREC_CHAR('t'): 224 attr->flags |= SECUREC_FLAG_PTRDIFF; 225 break; 226#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 227 case SECUREC_CHAR('z'): 228 attr->flags |= SECUREC_FLAG_SIZE; 229 break; 230 case SECUREC_CHAR('Z'): 231 attr->flags |= SECUREC_FLAG_SIZE; 232 break; 233#endif 234 235 case SECUREC_CHAR('I'): 236#ifdef SECUREC_ON_64BITS 237 attr->flags |= SECUREC_FLAG_I64; /* %I to INT64 */ 238#endif 239 if ((**format == SECUREC_CHAR('6')) && (*((*format) + 1) == SECUREC_CHAR('4'))) { 240 (*format) += 2; 241 attr->flags |= SECUREC_FLAG_I64; /* %I64 to INT64 */ 242 } else if ((**format == SECUREC_CHAR('3')) && (*((*format) + 1) == SECUREC_CHAR('2'))) { 243 (*format) += 2; 244 attr->flags &= ~SECUREC_FLAG_I64; /* %I64 to INT32 */ 245 } else if ((**format == SECUREC_CHAR('d')) || (**format == SECUREC_CHAR('i')) || 246 (**format == SECUREC_CHAR('o')) || (**format == SECUREC_CHAR('u')) || 247 (**format == SECUREC_CHAR('x')) || (**format == SECUREC_CHAR('X'))) { 248 /* do nothing */ 249 } else { 250 /* Compatibility code for "%I" just print I */ 251 return -1; 252 } 253 break; 254 255 case SECUREC_CHAR('h'): 256 if (**format == SECUREC_CHAR('h')) 257 attr->flags |= SECUREC_FLAG_CHAR; /* char */ 258 else 259 attr->flags |= SECUREC_FLAG_SHORT; /* short int */ 260 break; 261 262 case SECUREC_CHAR('w'): 263 attr->flags |= SECUREC_FLAG_WIDECHAR; /* wide char */ 264 break; 265 default: 266 break; 267 268 } 269 270 return 0; 271} 272 273static int SecDecodeTypeC(SecFormatAttr *attr, unsigned int cValue, SecFormatBuf *formatBuf, SecBuffer *buffer) 274{ 275 int textLen; 276 wchar_t wchar; 277 278#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && !(defined(__hpux)) && !(defined(SECUREC_ON_SOLARIS)) 279 attr->flags &= ~SECUREC_FLAG_LEADZERO; 280#endif 281 282#ifdef SECUREC_FOR_WCHAR 283 attr->bufferIsWide = 1; 284 wchar = (wchar_t)cValue; 285 if (attr->flags & SECUREC_FLAG_SHORT) { 286 /* multibyte character to wide character */ 287 char tempchar[2]; 288 tempchar[0] = (char)(wchar & 0x00ff); 289 tempchar[1] = '\0'; 290 291 if (mbtowc(buffer->wStr, tempchar, sizeof(tempchar)) < 0) { 292 return -1; 293 } 294 } else { 295 buffer->wStr[0] = wchar; 296 } 297 formatBuf->wStr = buffer->wStr; 298 textLen = 1; /* only 1 wide character */ 299#else 300 attr->bufferIsWide = 0; 301 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { 302 wchar = (wchar_t)cValue; 303 /* wide character to multibyte character */ 304 SECUREC_MASK_MSVC_CRT_WARNING 305 textLen = wctomb(buffer->str, wchar); 306 SECUREC_END_MASK_MSVC_CRT_WARNING 307 if (textLen < 0) { 308 return -1; 309 } 310 } else { 311 /* get multibyte character from argument */ 312 unsigned short temp; 313 temp = (unsigned short)cValue; 314 buffer->str[0] = (char)temp; 315 textLen = 1; 316 } 317 formatBuf->str = buffer->str; 318#endif 319 320 return textLen; 321} 322 323static int SecDecodeTypeS(SecFormatAttr *attr, char *argPtr, SecFormatBuf *formatBuf) 324{ 325 /* literal string to print null ptr, define it on stack rather than const text area 326 is to avoid gcc warning with pointing const text with variable */ 327 static char strNullString[8] = "(null)"; 328 static wchar_t wStrNullString[8] = { L'(', L'n', L'u', L'l', L'l', L')', L'\0', L'\0' }; 329 330 int finalPrecision; 331 char *strEnd = NULL; 332 wchar_t *wStrEnd = NULL; 333 int textLen; 334 335#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT)) && (!defined(SECUREC_ON_UNIX)) 336 attr->flags &= ~SECUREC_FLAG_LEADZERO; 337#endif 338 finalPrecision = (attr->precision == -1) ? SECUREC_INT_MAX : attr->precision; 339 formatBuf->str = argPtr; 340 341#ifdef SECUREC_FOR_WCHAR 342#if defined(SECUREC_COMPATIBLE_LINUX_FORMAT) 343 if (!(attr->flags & SECUREC_FLAG_LONG)) { 344 attr->flags |= SECUREC_FLAG_SHORT; 345 } 346#endif 347 if (attr->flags & SECUREC_FLAG_SHORT) { 348 if (formatBuf->str == NULL) { /* NULL passed, use special string */ 349 formatBuf->str = strNullString; 350 } 351 strEnd = formatBuf->str; 352 for (textLen = 0; textLen < finalPrecision && *strEnd; textLen++) { 353 ++strEnd; 354 } 355 /* textLen now contains length in multibyte chars */ 356 } else { 357 if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ 358 formatBuf->wStr = wStrNullString; 359 } 360 attr->bufferIsWide = 1; 361 wStrEnd = formatBuf->wStr; 362 while (finalPrecision-- && *wStrEnd) { 363 ++wStrEnd; 364 } 365 textLen = (int)(wStrEnd - formatBuf->wStr); /* in wchar_ts */ 366 /* textLen now contains length in wide chars */ 367 } 368#else /* SECUREC_FOR_WCHAR */ 369 if (attr->flags & (SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR)) { 370 if (formatBuf->wStr == NULL) { /* NULL passed, use special string */ 371 formatBuf->wStr = wStrNullString; 372 } 373 attr->bufferIsWide = 1; 374 wStrEnd = formatBuf->wStr; 375 while (finalPrecision-- && *wStrEnd) { 376 ++wStrEnd; 377 } 378 textLen = (int)(wStrEnd - formatBuf->wStr); 379 } else { 380 if (formatBuf->str == NULL) { /* meet NULL, use special string */ 381 formatBuf->str = strNullString; 382 } 383 384 if (finalPrecision == SECUREC_INT_MAX) { 385 /* precision NOT assigned */ 386 /* The strlen performance is high when the string length is greater than 32 */ 387 textLen = (int)strlen(formatBuf->str); 388 } else { 389 /* precision assigned */ 390 strEnd = formatBuf->str; 391 while (finalPrecision-- && *strEnd) { 392 ++strEnd; 393 } 394 textLen = (int)(strEnd - formatBuf->str); /* length of the string */ 395 } 396 397 } 398 399#endif /* SECUREC_FOR_WCHAR */ 400 return textLen; 401} 402 403HILOG_LOCAL_API 404int SecOutputPS(SecPrintfStream *stream, int priv, const char *cformat, va_list arglist) 405{ 406 const SecChar *format = cformat; 407 408 char *floatBuf = NULL; 409 SecFormatBuf formatBuf; 410 static const char *itoaUpperDigits = "0123456789ABCDEFX"; 411 static const char *itoaLowerDigits = "0123456789abcdefx"; 412 const char *digits = itoaUpperDigits; 413 int ii = 0; 414 415 unsigned int radix; 416 int charsOut; /* characters written */ 417 418 int prefixLen = 0; 419 int padding = 0; 420 421 int textLen; /* length of the text */ 422 int bufferSize = 0; /* size of formatBuf.str */ 423 int noOutput = 0; 424 425 SecFmtState state; 426 SecFmtState laststate; 427 428 SecChar prefix[2] = { 0 }; 429 SecChar ch; /* currently read character */ 430 431 static const unsigned char fmtCharTable[337] = { 432 /* type 0: nospecial meaning; 433 1: '%'; 434 2: '.' 435 3: '*' 436 4: '0' 437 5: '1' ... '9' 438 6: ' ', '+', '-', '#' 439 7: 'h', 'l', 'L', 'F', 'w' , 'N','z','q','t','j' 440 8: 'd','o','u','i','x','X','e','f','g' 441 */ 442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 443 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 444 0x06, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x06, 0x02, 0x00, 445 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 446 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x00, 0x07, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 447 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 448 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x07, 0x00, 0x07, 0x00, 0x00, 0x08, 449 0x08, 0x07, 0x00, 0x08, 0x07, 0x08, 0x00, 0x07, 0x08, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 450 /* fill zero for normal char 128 byte for 0x80 - 0xff */ 451 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 452 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 454 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 459 /* state 0: normal 460 1: percent 461 2: flag 462 3: width 463 4: dot 464 5: precis 465 6: size 466 7: type 467 8: invalid 468 */ 469 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 470 0x01, 0x00, 0x00, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 0x08, 0x05, 471 0x08, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x03, 0x03, 472 0x03, 0x05, 0x05, 0x08, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 473 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 474 0x00 475 }; 476 477 SecFormatAttr formatAttr; 478 SecBuffer buffer; 479 formatAttr.flags = 0; 480 formatAttr.bufferIsWide = 0; /* flag for buffer contains wide chars */ 481 formatAttr.fldWidth = 0; 482 formatAttr.precision = 0; 483 formatAttr.dynWidth = 0; 484 formatAttr.dynPrecision = 0; 485 486 charsOut = 0; 487 textLen = 0; 488 state = STAT_NORMAL; /* starting state */ 489 formatBuf.str = NULL; 490 491 int isPrivacy = 1; /*whether show private string*/ 492 493 /* loop each format character */ 494 /* remove format != NULL */ 495 while ((ch = *format++) != SECUREC_CHAR('\0') && charsOut >= 0) { 496 laststate = state; 497 state = SECUREC_DECODE_STATE(ch, fmtCharTable, laststate); 498 499 switch (state) { 500 case STAT_NORMAL: 501 502NORMAL_CHAR: 503 504 /* normal state, write character */ 505 if (SECUREC_IS_REST_BUF_ENOUGH(1 /* only one char */ )) { 506 SECUREC_SAFE_WRITE_CHAR(ch, stream, &charsOut); /* char * cast to wchar * */ 507 } else { 508#ifdef SECUREC_FOR_WCHAR 509 SECUREC_WRITE_CHAR(ch, stream, &charsOut); 510#else 511 /* optimize function call to code */ 512 charsOut = -1; 513 stream->count = -1; 514#endif 515 } 516 517 continue; 518 519 case STAT_PERCENT: 520 /* set default values */ 521 prefixLen = 0; 522 noOutput = 0; 523 formatAttr.flags = 0; 524 formatAttr.fldWidth = 0; 525 formatAttr.precision = -1; 526 formatAttr.bufferIsWide = 0; 527 if (*format == SECUREC_CHAR('{')) { 528 if (strncmp(format, PUBLIC_FLAG, PUBLIC_FLAG_LEN) == 0) { 529 isPrivacy = 0; 530 format += PUBLIC_FLAG_LEN; 531 } 532 else if (strncmp(format, PRIVATE_FLAG, PRIVATE_FLAG_LEN) == 0) { 533 isPrivacy = 1; 534 format += PRIVATE_FLAG_LEN; 535 } 536 } 537 else { 538 isPrivacy = 1; 539 } 540 541 if (0 == priv) { 542 isPrivacy = 0; 543 } 544 545 break; 546 547 case STAT_FLAG: 548 /* set flag based on which flag character */ 549 SecDecodeFlags(ch, &formatAttr); 550 break; 551 552 case STAT_WIDTH: 553 /* update width value */ 554 if (ch == SECUREC_CHAR('*')) { 555 /* get width */ 556 formatAttr.fldWidth = (int)va_arg(arglist, int); 557 if (formatAttr.fldWidth < 0) { 558 formatAttr.flags |= SECUREC_FLAG_LEFT; 559 formatAttr.fldWidth = -formatAttr.fldWidth; 560 } 561 formatAttr.dynWidth = 1; 562 } else { 563 if (laststate != STAT_WIDTH) { 564 formatAttr.fldWidth = 0; 565 } 566 if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.fldWidth)) { 567 return -1; 568 } 569 formatAttr.fldWidth = (int)SECUREC_MUL10((unsigned int)formatAttr.fldWidth) + (ch - SECUREC_CHAR('0')); 570 formatAttr.dynWidth = 0; 571 } 572 break; 573 574 case STAT_DOT: 575 formatAttr.precision = 0; 576 break; 577 578 case STAT_PRECIS: 579 /* update precision value */ 580 if (ch == SECUREC_CHAR('*')) { 581 /* get precision from arg list */ 582 formatAttr.precision = (int)va_arg(arglist, int); 583 if (formatAttr.precision < 0) { 584 formatAttr.precision = -1; 585 } 586 formatAttr.dynPrecision = 1; 587 } else { 588 /* add digit to current precision */ 589 if (SECUREC_MUL10_ADD_BEYOND_MAX(formatAttr.precision)) { 590 return -1; 591 } 592 formatAttr.precision = 593 (int)SECUREC_MUL10((unsigned int)formatAttr.precision) + (ch - SECUREC_CHAR('0')); 594 formatAttr.dynPrecision = 0; 595 } 596 break; 597 598 case STAT_SIZE: 599 /* read a size specifier, set the formatAttr.flags based on it */ 600 if (SecDecodeSize(ch, &formatAttr, &format) != 0) { 601 /* Compatibility code for "%I" just print I */ 602 state = STAT_NORMAL; 603 goto NORMAL_CHAR; 604 } 605 break; 606 607 case STAT_TYPE: 608 609 switch (ch) { 610 611 case SECUREC_CHAR('C'): 612 /* wide char */ 613 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 614 615#ifdef SECUREC_FOR_WCHAR 616 formatAttr.flags |= SECUREC_FLAG_SHORT; 617#else 618 formatAttr.flags |= SECUREC_FLAG_WIDECHAR; 619#endif 620 } 621 /* fall-through */ 622 /* FALLTHRU */ 623 case SECUREC_CHAR('c'): 624 { 625 unsigned int cValue = (unsigned int)va_arg(arglist, int); 626 /*if it's a private arg, just write <priate> to stream*/ 627 if (isPrivacy == 1) { 628 break; 629 } 630 textLen = SecDecodeTypeC(&formatAttr, cValue, &formatBuf, &buffer); 631 if (textLen < 0) { 632 noOutput = 1; 633 } 634 } 635 break; 636 case SECUREC_CHAR('S'): /* wide char string */ 637#ifndef SECUREC_FOR_WCHAR 638 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 639 formatAttr.flags |= SECUREC_FLAG_WIDECHAR; 640 } 641#else 642 if (!(formatAttr.flags & (SECUREC_FLAG_SHORT | SECUREC_FLAG_LONG | SECUREC_FLAG_WIDECHAR))) { 643 formatAttr.flags |= SECUREC_FLAG_SHORT; 644 } 645#endif 646 /* fall-through */ 647 /* FALLTHRU */ 648 case SECUREC_CHAR('s'): 649 { 650 char *argPtr = (char *)va_arg(arglist, char *); 651 /*if it's a private arg, just write <priate> to stream*/ 652 if (isPrivacy == 1) { 653 break; 654 } 655 textLen = SecDecodeTypeS(&formatAttr, argPtr, &formatBuf); 656 } 657 break; 658 659 case SECUREC_CHAR('n'): 660 /* higher risk disable it */ 661 return -1; 662 663 case SECUREC_CHAR('E'): /* fall-through */ /* FALLTHRU */ 664 case SECUREC_CHAR('F'): /* fall-through */ /* FALLTHRU */ 665 case SECUREC_CHAR('G'): /* fall-through */ /* FALLTHRU */ 666 case SECUREC_CHAR('A'): /* fall-through */ /* FALLTHRU */ 667 /* convert format char to lower , use Explicit conversion to clean up compilation warning */ 668 ch = (SecChar) (ch + ((SecChar) (SECUREC_CHAR('a')) - (SECUREC_CHAR('A')))); 669 /* fall-through */ 670 /* FALLTHRU */ 671 case SECUREC_CHAR('e'): /* fall-through */ /* FALLTHRU */ 672 case SECUREC_CHAR('f'): /* fall-through */ /* FALLTHRU */ 673 case SECUREC_CHAR('g'): /* fall-through */ /* FALLTHRU */ 674 case SECUREC_CHAR('a'): 675 { 676 /*if it's a private arg, just write <priate> to stream*/ 677 if (isPrivacy == 1) { 678#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 679 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 680 (void)va_arg(arglist, long double); 681 } else 682#endif 683 { 684 (void)va_arg(arglist, double); 685 } 686 break; 687 } 688 689 /* floating point conversion */ 690 formatBuf.str = buffer.str; /* output buffer for float string with default size */ 691 692 /* compute the precision value */ 693 if (formatAttr.precision < 0) { 694 formatAttr.precision = 6; 695 } else if (formatAttr.precision == 0 && ch == SECUREC_CHAR('g')) { 696 formatAttr.precision = 1; 697 } 698 699 /* calc buffer size to store long double value */ 700 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 701 if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE_LB)) { 702 noOutput = 1; 703 break; 704 } 705 bufferSize = SECUREC_FLOAT_BUFSIZE_LB + formatAttr.precision; 706 } else { 707 if (formatAttr.precision > (SECUREC_INT_MAX - SECUREC_FLOAT_BUFSIZE)) { 708 noOutput = 1; 709 break; 710 } 711 bufferSize = SECUREC_FLOAT_BUFSIZE + formatAttr.precision; 712 } 713 if (formatAttr.fldWidth > bufferSize) { 714 bufferSize = formatAttr.fldWidth; 715 } 716 717 if (bufferSize >= SECUREC_BUFFER_SIZE) { 718 /* the current value of SECUREC_BUFFER_SIZE could NOT store the formatted float string */ 719 /* size include '+' and '\0' */ 720 floatBuf = (char *)SECUREC_MALLOC(((size_t)(unsigned int)bufferSize + (size_t)2)); 721 if (floatBuf != NULL) { 722 formatBuf.str = floatBuf; 723 } else { 724 noOutput = 1; 725 break; 726 } 727 } 728 729 { 730 /* add following code to call system sprintf API for float number */ 731 const SecChar *pFltFmt = format - 2; /* point to the position before 'f' or 'g' */ 732 int k; 733 int fltFmtStrLen; 734 char fltFmtBuf[SECUREC_FMT_STR_LEN]; 735 char *fltFmtStr = fltFmtBuf; 736 char *fltFmtHeap = NULL; /* to clear warning */ 737 738 /* must meet '%' (normal format) or '}'(with{private} or{public} format)*/ 739 while (SECUREC_CHAR('%') != *pFltFmt && SECUREC_CHAR('}') != *pFltFmt) { 740 --pFltFmt; 741 } 742 fltFmtStrLen = (int)((format - pFltFmt) + 1); /* with ending terminator */ 743 if (fltFmtStrLen > SECUREC_FMT_STR_LEN) { 744 /* if SECUREC_FMT_STR_LEN is NOT enough, alloc a new buffer */ 745 fltFmtHeap = (char *)SECUREC_MALLOC((size_t)((unsigned int)fltFmtStrLen)); 746 if (fltFmtHeap == NULL) { 747 noOutput = 1; 748 break; 749 } else { 750 fltFmtHeap[0] = '%'; 751 for (k = 1; k < fltFmtStrLen - 1; ++k) { 752 /* convert wchar to char */ 753 fltFmtHeap[k] = (char)(pFltFmt[k]); /* copy the format string */ 754 } 755 fltFmtHeap[k] = '\0'; 756 757 fltFmtStr = fltFmtHeap; 758 } 759 } else { 760 /* purpose of the repeat code is to solve the tool alarm Redundant_Null_Check */ 761 fltFmtBuf[0] = '%'; 762 for (k = 1; k < fltFmtStrLen - 1; ++k) { 763 /* convert wchar to char */ 764 fltFmtBuf[k] = (char)(pFltFmt[k]); /* copy the format string */ 765 } 766 fltFmtBuf[k] = '\0'; 767 } 768 769#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 770 if (formatAttr.flags & SECUREC_FLAG_LONG_DOUBLE) { 771 long double tmp = (long double)va_arg(arglist, long double); 772 /* call system sprintf to format float value */ 773 if (formatAttr.dynWidth && formatAttr.dynPrecision) { 774 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, 775 formatAttr.fldWidth,formatAttr.precision, tmp); 776 } else if (formatAttr.dynWidth) { 777 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, 778 formatAttr.fldWidth, tmp); 779 } else if (formatAttr.dynPrecision) { 780 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, 781 formatAttr.precision, tmp); 782 } else { 783 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp); 784 } 785 } else 786#endif 787 { 788 double tmp = (double)va_arg(arglist, double); 789 if (formatAttr.dynWidth && formatAttr.dynPrecision) { 790 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth, 791 formatAttr.precision, tmp); 792 } else if (formatAttr.dynWidth) { 793 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.fldWidth, 794 tmp); 795 } else if (formatAttr.dynPrecision) { 796 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, formatAttr.precision, 797 tmp); 798 } else { 799 textLen = SecIndirectSprintf(formatBuf.str, (char *)fltFmtStr, tmp); 800 } 801 } 802 803 if (fltFmtHeap != NULL) { 804 /* if buffer is allocated on heap, free it */ 805 SECUREC_FREE(fltFmtHeap); 806 fltFmtHeap = NULL; 807 /* to clear e438 last value assigned not used , the compiler will optimize this code */ 808 (void)fltFmtHeap; 809 } 810 if (textLen < 0) { 811 /* bufferSize is large enough,just validation the return value */ 812 noOutput = 1; 813 break; 814 } 815 816 formatAttr.fldWidth = textLen; /* no padding ,this variable to calculate amount of padding */ 817 prefixLen = 0; /* no padding ,this variable to calculate amount of padding */ 818 formatAttr.flags = 0; /* clear all internal formatAttr.flags */ 819 break; 820 } 821 } 822 823 case SECUREC_CHAR('p'): 824 /* print a pointer */ 825#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 826 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 827#else 828 formatAttr.flags |= SECUREC_FLAG_POINTER; 829#endif 830 831#ifdef SECUREC_ON_64BITS 832 formatAttr.flags |= SECUREC_FLAG_I64; /* converting an int64 */ 833#else 834 formatAttr.flags |= SECUREC_FLAG_LONG; /* converting a long */ 835#endif 836 837#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) && (!defined(SECUREC_ON_UNIX)) 838 839#if defined(SECUREC_VXWORKS_PLATFORM) 840 formatAttr.precision = 1; 841#else 842 formatAttr.precision = 0; 843#endif 844 formatAttr.flags |= SECUREC_FLAG_ALTERNATE; /* "0x" is not default prefix in UNIX */ 845 digits = itoaLowerDigits; 846 goto OUTPUT_HEX; 847#else 848/* not linux vxwoks */ 849#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 850 formatAttr.precision = 1; 851#else 852 formatAttr.precision = 2 * sizeof(void *); 853#endif 854 855#endif 856 857#if defined(SECUREC_ON_UNIX) 858 digits = itoaLowerDigits; 859 goto OUTPUT_HEX; 860#endif 861 862 /* fall-through */ 863 /* FALLTHRU */ 864 case SECUREC_CHAR('X'): 865 /* unsigned upper hex output */ 866 digits = itoaUpperDigits; 867 goto OUTPUT_HEX; 868 case SECUREC_CHAR('x'): 869 /* unsigned lower hex output */ 870 digits = itoaLowerDigits; 871 872OUTPUT_HEX: 873 radix = 16; 874 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { 875 /* alternate form means '0x' prefix */ 876 prefix[0] = SECUREC_CHAR('0'); 877 prefix[1] = (SecChar) (digits[16]); /* 'x' or 'X' */ 878 879#if (defined(SECUREC_COMPATIBLE_LINUX_FORMAT) || defined(SECUREC_VXWORKS_PLATFORM)) 880 if (ch == 'p') { 881 prefix[1] = SECUREC_CHAR('x'); 882 } 883#endif 884#if defined(_AIX) || defined(SECUREC_ON_SOLARIS) 885 if (ch == 'p') { 886 prefixLen = 0; 887 } else { 888 prefixLen = 2; 889 } 890#else 891 prefixLen = 2; 892#endif 893 894 } 895 goto OUTPUT_INT; 896 case SECUREC_CHAR('i'): /* fall-through */ /* FALLTHRU */ 897 case SECUREC_CHAR('d'): /* fall-through */ /* FALLTHRU */ 898 /* signed decimal output */ 899 formatAttr.flags |= SECUREC_FLAG_SIGNED; 900 /* fall-through */ 901 /* FALLTHRU */ 902 case SECUREC_CHAR('u'): 903 radix = 10; 904 goto OUTPUT_INT; 905 case SECUREC_CHAR('o'): 906 /* unsigned octal output */ 907 radix = 8; 908 if (formatAttr.flags & SECUREC_FLAG_ALTERNATE) { 909 /* alternate form means force a leading 0 */ 910 formatAttr.flags |= SECUREC_FLAG_FORCE_OCTAL; 911 } 912OUTPUT_INT: 913 { 914 915 SecUnsignedInt64 number = 0; /* number to convert */ 916 SecInt64 l; /* temp long value */ 917 unsigned char tch; 918#if defined(SECUREC_VXWORKS_VERSION_5_4) && !defined(SECUREC_ON_64BITS) 919 SecUnsignedInt32 digit = 0; /* ascii value of digit */ 920 SecUnsignedInt32 quotientHigh = 0; 921 SecUnsignedInt32 quotientLow = 0; 922#endif 923 924 /* read argument into variable l */ 925 if (formatAttr.flags & SECUREC_FLAG_I64) { 926 l = (SecInt64)va_arg(arglist, SecInt64); 927 } else if (formatAttr.flags & SECUREC_FLAG_LONGLONG) { 928 l = (SecInt64)va_arg(arglist, SecInt64); 929 } else 930#ifdef SECUREC_ON_64BITS 931 if (formatAttr.flags & SECUREC_FLAG_LONG) { 932 l = (long)va_arg(arglist, long); 933 } else 934#endif /* SECUREC_ON_64BITS */ 935 if (formatAttr.flags & SECUREC_FLAG_CHAR) { 936 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 937 l = (char)va_arg(arglist, int); /* sign extend */ 938 if (l >= 128) { /* on some platform, char is always unsigned */ 939 SecUnsignedInt64 tmpL = (SecUnsignedInt64)l; 940 formatAttr.flags |= SECUREC_FLAG_NEGATIVE; 941 tch = (unsigned char)(~(tmpL)); 942 l = tch + 1; 943 } 944 } else { 945 l = (unsigned char)va_arg(arglist, int); /* zero-extend */ 946 } 947 948 } else if (formatAttr.flags & SECUREC_FLAG_SHORT) { 949 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 950 l = (short)va_arg(arglist, int); /* sign extend */ 951 } else { 952 l = (unsigned short)va_arg(arglist, int); /* zero-extend */ 953 } 954 955 } 956#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 957 else if (formatAttr.flags & SECUREC_FLAG_PTRDIFF) { 958 l = (ptrdiff_t)va_arg(arglist, ptrdiff_t); /* sign extend */ 959 } else if (formatAttr.flags & SECUREC_FLAG_SIZE) { 960 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 961 /* No suitable macros were found to handle the branch */ 962 if (SecIsSameSize(sizeof(size_t), sizeof(long))) { 963 l = va_arg(arglist, long); /* sign extend */ 964 } else if (SecIsSameSize(sizeof(size_t), sizeof(long long))) { 965 l = va_arg(arglist, long long); /* sign extend */ 966 } else { 967 l = va_arg(arglist, int); /* sign extend */ 968 } 969 } else { 970 l = (SecInt64)(size_t)va_arg(arglist, size_t); /* sign extend */ 971 } 972 } else if (formatAttr.flags & SECUREC_FLAG_INTMAX) { 973 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 974 l = va_arg(arglist, SecInt64); /* sign extend */ 975 } else { 976 l = (SecInt64)(SecUnsignedInt64)va_arg(arglist, SecUnsignedInt64); /* sign extend */ 977 } 978 } 979#endif 980 else { 981 if (formatAttr.flags & SECUREC_FLAG_SIGNED) { 982 l = va_arg(arglist, int); /* sign extend */ 983 } else { 984 l = (unsigned int)va_arg(arglist, int); /* zero-extend */ 985 } 986 987 } 988 /*if it's a private arg, just write <priate> to stream*/ 989 if (isPrivacy == 1) { 990 break; 991 } 992 993 /* check for negative; copy into number */ 994 if ((formatAttr.flags & SECUREC_FLAG_SIGNED) && l < 0) { 995 number = (SecUnsignedInt64)(-l); 996 formatAttr.flags |= SECUREC_FLAG_NEGATIVE; 997 } else { 998 number = (SecUnsignedInt64)l; 999 } 1000 1001 if (((formatAttr.flags & SECUREC_FLAG_I64) == 0) && 1002#ifdef SECUREC_COMPATIBLE_LINUX_FORMAT 1003 ((formatAttr.flags & SECUREC_FLAG_INTMAX) == 0) && 1004#endif 1005#ifdef SECUREC_ON_64BITS 1006 ((formatAttr.flags & SECUREC_FLAG_PTRDIFF) == 0) && 1007 ((formatAttr.flags & SECUREC_FLAG_SIZE) == 0) && 1008#if !defined(SECUREC_COMPATIBLE_WIN_FORMAT) /* on window 64 system sizeof long is 32bit */ 1009 ((formatAttr.flags & SECUREC_FLAG_LONG) == 0) && 1010#endif 1011#endif 1012 ((formatAttr.flags & SECUREC_FLAG_LONGLONG) == 0)) { 1013 1014 number &= 0xffffffff; 1015 } 1016 1017 /* check precision value for default */ 1018 if (formatAttr.precision < 0) { 1019 formatAttr.precision = 1; /* default precision */ 1020 } else { 1021#if defined(SECUREC_COMPATIBLE_WIN_FORMAT) 1022 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1023#else 1024 if (!(formatAttr.flags & SECUREC_FLAG_POINTER)) { 1025 formatAttr.flags &= ~SECUREC_FLAG_LEADZERO; 1026 } 1027#endif 1028 if (formatAttr.precision > SECUREC_MAX_PRECISION) { 1029 formatAttr.precision = SECUREC_MAX_PRECISION; 1030 } 1031 } 1032 1033 /* Check if data is 0; if so, turn off hex prefix,if 'p',add 0x prefix,else not add prefix */ 1034 if (number == 0) { 1035#if !(defined(SECUREC_VXWORKS_PLATFORM)||defined(__hpux)) 1036 prefixLen = 0; 1037#else 1038 if ((ch == 'p') && (formatAttr.flags & SECUREC_FLAG_ALTERNATE)) 1039 prefixLen = 2; 1040 else 1041 prefixLen = 0; 1042#endif 1043 } 1044 1045 /* Convert data to ASCII */ 1046 formatBuf.str = &buffer.str[SECUREC_BUFFER_SIZE]; 1047 1048 if (number > 0) { 1049#ifdef SECUREC_ON_64BITS 1050 switch (radix) { 1051 /* the compiler will optimize each one */ 1052 SECUREC_SPECIAL(number, 10); 1053 break; 1054 SECUREC_SPECIAL(number, 16); 1055 break; 1056 SECUREC_SPECIAL(number, 8); 1057 break; 1058 default: 1059 break; 1060 } 1061#else /* for 32 bits system */ 1062 if (number <= 0xFFFFFFFFUL) { 1063 /* in most case, the value to be converted is small value */ 1064 SecUnsignedInt32 n32Tmp = (SecUnsignedInt32)number; 1065 switch (radix) { 1066 SECUREC_SPECIAL(n32Tmp, 16); 1067 break; 1068 SECUREC_SPECIAL(n32Tmp, 8); 1069 break; 1070 1071#ifdef _AIX 1072 /* the compiler will optimize div 10 */ 1073 SECUREC_SPECIAL(n32Tmp, 10); 1074 break; 1075#else 1076 case 10: 1077 { 1078 /* fast div 10 */ 1079 SecUnsignedInt32 q; 1080 SecUnsignedInt32 r; 1081 do { 1082 *--formatBuf.str = digits[n32Tmp % 10]; 1083 q = (n32Tmp >> 1) + (n32Tmp >> 2); 1084 q = q + (q >> 4); 1085 q = q + (q >> 8); 1086 q = q + (q >> 16); 1087 q = q >> 3; 1088 r = n32Tmp - (((q << 2) + q) << 1); 1089 n32Tmp = (r > 9) ? (q + 1) : q; 1090 } while (n32Tmp != 0); 1091 } 1092 break; 1093#endif 1094 default: 1095 break; 1096 } /* end switch */ 1097 } else { 1098 /* the value to be converted is greater than 4G */ 1099#if defined(SECUREC_VXWORKS_VERSION_5_4) 1100 do { 1101 if (0 != SecU64Div32((SecUnsignedInt32)((number >> 16) >> 16), 1102 (SecUnsignedInt32)number, 1103 (SecUnsignedInt32)radix, "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