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