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