Changeset 1c38445 in mainline for uspace/lib/libc/generic/io/printf_core.c
- Timestamp:
- 2007-10-04T15:00:19Z (17 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f7fad5a
- Parents:
- 18525c5
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libc/generic/io/printf_core.c
r18525c5 r1c38445 77 77 * @return number of printed characters 78 78 */ 79 static int printf_putnchars(const char * buf, size_t count, struct printf_spec *ps) 79 static int printf_putnchars(const char * buf, size_t count, 80 struct printf_spec *ps) 80 81 { 81 82 return ps->write((void *)buf, count, ps->data); … … 125 126 126 127 if (!(flags & __PRINTF_FLAG_LEFTALIGNED)) { 127 while (--width > 0) { /* one space is consumed by character itself hence predecrement */ 128 /* 129 * One space is consumed by the character itself, hence the 130 * predecrement. 131 */ 132 while (--width > 0) { 128 133 if (printf_putchar(' ', ps) > 0) 129 134 ++counter; … … 133 138 if (printf_putchar(c, ps) > 0) 134 139 counter++; 135 136 while (--width > 0) { /* one space is consumed by character itself hence predecrement */ 140 /* 141 * One space is consumed by the character itself, hence the 142 * predecrement. 143 */ 144 while (--width > 0) { 137 145 if (printf_putchar(' ', ps) > 0) 138 146 ++counter; … … 149 157 * @return number of printed characters 150 158 */ 151 152 static int print_string(char *s, int width, int precision, uint64_t flags,struct printf_spec *ps)159 static int print_string(char *s, int width, int precision, uint64_t flags, 160 struct printf_spec *ps) 153 161 { 154 162 int counter = 0; … … 176 184 } 177 185 178 while (precision > size) { 179 precision--; 180 if (printf_putchar(' ', ps) == 1) 181 ++counter; 182 } 183 184 if ((retval = printf_putnchars(s, precision, ps)) < 0) { 186 if ((retval = printf_putnchars(s, size < precision ? size : precision, 187 ps)) < 0) { 185 188 return -counter; 186 189 } … … 211 214 * 212 215 */ 213 static int print_number(uint64_t num, int width, int precision, int base , uint64_t flags, struct printf_spec *ps) 216 static int print_number(uint64_t num, int width, int precision, int base, 217 uint64_t flags, struct printf_spec *ps) 214 218 { 215 219 char *digits = digits_small; 216 char d[PRINT_NUMBER_BUFFER_SIZE]; /* this is good enough even for base == 2, prefix and sign */ 220 char d[PRINT_NUMBER_BUFFER_SIZE]; /* this is good enough even for 221 * base == 2, prefix and sign */ 217 222 char *ptr = &d[PRINT_NUMBER_BUFFER_SIZE - 1]; 218 223 int size = 0; /* size of number with all prefixes and signs */ … … 239 244 number_size = size; 240 245 241 /* Collect sum of all prefixes/signs/... to calculate padding and leading zeroes */ 246 /* 247 * Collect sum of all prefixes/signs/... to calculate padding and 248 * leading zeroes 249 */ 242 250 if (flags & __PRINTF_FLAG_PREFIX) { 243 251 switch(base) { … … 260 268 size++; 261 269 } else if (flags & __PRINTF_FLAG_SHOWPLUS) { 262 263 264 265 266 267 270 sgn = '+'; 271 size++; 272 } else if (flags & __PRINTF_FLAG_SPACESIGN) { 273 sgn = ' '; 274 size++; 275 } 268 276 } 269 277 … … 272 280 } 273 281 274 /* if number is leftaligned or precision is specified then zeropadding is ignored */ 282 /* 283 * If number is leftaligned or precision is specified then zeropadding 284 * is ignored. 285 */ 275 286 if (flags & __PRINTF_FLAG_ZEROPADDED) { 276 287 if ((precision == 0) && (width > size)) { … … 280 291 281 292 /* print leading spaces */ 282 if (number_size > precision) /* We must print whole number not only a part */ 293 294 /* We must print whole number not only a part. */ 295 if (number_size > precision) 283 296 precision = number_size; 284 297 … … 358 371 /** Print formatted string. 359 372 * 360 * Print string formatted according to the fmt parameter 361 * and variadic arguments. Each formatting directive 362 * must have the following form: 373 * Print string formatted according to the fmt parameter and variadic arguments. 374 * Each formatting directive must have the following form: 363 375 * 364 376 * \% [ FLAGS ] [ WIDTH ] [ .PRECISION ] [ TYPE ] CONVERSION … … 366 378 * FLAGS:@n 367 379 * - "#" Force to print prefix. 368 * For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and 0X369 * and for conversion \%b the prefix is 0b.380 * For conversion \%o the prefix is 0, for %x and \%X prefixes are 0x and 381 * 0X and for conversion \%b the prefix is 0b. 370 382 * 371 383 * - "-" Align to left. … … 373 385 * - "+" Print positive sign just as negative. 374 386 * 375 * - " " If the printed number is positive and "+" flag is not set, print space in 376 * place of sign. 377 * 378 * - "0" Print 0 as padding instead of spaces. Zeroes are placed between sign and the 379 * rest of the number. This flag is ignored if "-" flag is specified. 387 * - " " If the printed number is positive and "+" flag is not set, 388 * print space in place of sign. 389 * 390 * - "0" Print 0 as padding instead of spaces. Zeroes are placed between 391 * sign and the rest of the number. This flag is ignored if "-" 392 * flag is specified. 380 393 * 381 394 * WIDTH:@n 382 * - Specify minimal width of printed argument. If it is bigger, width is ignored.383 * If width is specified with a "*" character instead of number, width is taken from384 * parameter list. And integer parameter is expected before parameter for processed385 * conversion specification. If this value is negative its absolute value is taken386 * and the "-" flag is set.395 * - Specify minimal width of printed argument. If it is bigger, width is 396 * ignored. If width is specified with a "*" character instead of number, 397 * width is taken from parameter list. And integer parameter is expected 398 * before parameter for processed conversion specification. If this value 399 * is negative its absolute value is taken and the "-" flag is set. 387 400 * 388 401 * PRECISION:@n 389 402 * - Value precision. For numbers it specifies minimum valid numbers. 390 * Smaller numbers are printed with leading zeroes. Bigger numbers are not affected.391 * Strings with more than precision characters are cut off.392 * Just as with width, an "*" can be used used instead of a number.393 * An integer value is then expected in parameters. When both width and precision394 * are specified using "*", the first parameter is used for width and the second one395 * for precision.403 * Smaller numbers are printed with leading zeroes. Bigger numbers are 404 * not affected. Strings with more than precision characters are cut off. 405 * Just as with width, an "*" can be used used instead of a number. An 406 * integer value is then expected in parameters. When both width and 407 * precision are specified using "*", the first parameter is used for 408 * width and the second one for precision. 396 409 * 397 410 * TYPE:@n … … 409 422 * - c Print single character. 410 423 * 411 * - s Print zero terminated string. If a NULL value is passed as value, "(NULL)" is printed instead. 424 * - s Print zero terminated string. If a NULL value is passed as 425 * value, "(NULL)" is printed instead. 412 426 * 413 * - P, p Print value of a pointer. Void * value is expected and it is printed in hexadecimal notation with prefix 414 * (as with '\%#X' or '\%#x' for 32bit or '\%#X' or '\%#x' for 64bit long pointers). 415 * 416 * - b Print value as unsigned binary number. Prefix is not printed by default. (Nonstandard extension.) 427 * - P, p Print value of a pointer. Void * value is expected and it is 428 * printed in hexadecimal notation with prefix (as with '\%#X' or 429 * '\%#x' for 32bit or '\%#X' or '\%#x' for 64bit long pointers). 430 * 431 * - b Print value as unsigned binary number. Prefix is not printed by 432 * default. (Nonstandard extension.) 417 433 * 418 * - o Print value as unsigned octal number. Prefix is not printed by default. 419 * 420 * - d,i Print signed decimal number. There is no difference between d and i conversion. 434 * - o Print value as unsigned octal number. Prefix is not printed by 435 * default. 436 * 437 * - d, i Print signed decimal number. There is no difference between d 438 * and i conversion. 421 439 * 422 440 * - u Print unsigned decimal number. 423 441 * 424 * - X, x Print hexadecimal number with upper- or lower-case. Prefix is not printed by default. 442 * - X, x Print hexadecimal number with upper- or lower-case. Prefix is 443 * not printed by default. 425 444 * 426 * All other characters from fmt except the formatting directives 427 * are printed inverbatim.445 * All other characters from fmt except the formatting directives are printed in 446 * verbatim. 428 447 * 429 448 * @param fmt Formatting NULL terminated string. … … 432 451 int printf_core(const char *fmt, struct printf_spec *ps, va_list ap) 433 452 { 434 int i = 0, j = 0; /* i is index of currently processed char from fmt, j is index to the first not printed nonformating character */ 453 /* i is the index of the currently processed char from fmt */ 454 int i = 0; 455 /* j is the index to the first not printed nonformating character */ 456 int j = 0; 457 435 458 int end; 436 int counter; 437 int retval; 459 int counter; /* counter of printed characters */ 460 int retval; /* used to store return values from called functions */ 438 461 char c; 439 462 qualifier_t qualifier; /* type of argument */ 440 int base; /* base in which will be parameter (numbers only)printed */463 int base; /* base in which will be a numeric parameter printed */ 441 464 uint64_t number; /* argument value */ 442 size_t size; 465 size_t size; /* byte size of integer parameter */ 443 466 int width, precision; 444 467 uint64_t flags; … … 451 474 /* print common characters if any processed */ 452 475 if (i > j) { 453 if ((retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps)) < 0) { /* error */ 476 if ((retval = printf_putnchars(&fmt[j], 477 (size_t)(i - j), ps)) < 0) { /* error */ 454 478 goto minus_out; 455 479 } … … 465 489 ++i; 466 490 switch (c = fmt[i]) { 467 case '#': flags |= __PRINTF_FLAG_PREFIX; break; 468 case '-': flags |= __PRINTF_FLAG_LEFTALIGNED; break; 469 case '+': flags |= __PRINTF_FLAG_SHOWPLUS; break; 470 case ' ': flags |= __PRINTF_FLAG_SPACESIGN; break; 471 case '0': flags |= __PRINTF_FLAG_ZEROPADDED; break; 472 default: end = 1; 491 case '#': 492 flags |= __PRINTF_FLAG_PREFIX; 493 break; 494 case '-': 495 flags |= __PRINTF_FLAG_LEFTALIGNED; 496 break; 497 case '+': 498 flags |= __PRINTF_FLAG_SHOWPLUS; 499 break; 500 case ' ': 501 flags |= __PRINTF_FLAG_SPACESIGN; 502 break; 503 case '0': 504 flags |= __PRINTF_FLAG_ZEROPADDED; 505 break; 506 default: 507 end = 1; 473 508 }; 474 509 … … 487 522 width = (int)va_arg(ap, int); 488 523 if (width < 0) { 489 /* negative width means to set'-' flag */524 /* negative width sets '-' flag */ 490 525 width *= -1; 491 526 flags |= __PRINTF_FLAG_LEFTALIGNED; … … 503 538 } 504 539 } else if (fmt[i] == '*') { 505 /* get precision value from argument list*/540 /* get precision value from argument */ 506 541 i++; 507 542 precision = (int)va_arg(ap, int); 508 543 if (precision < 0) { 509 /* negative precision means to ignore it*/544 /* negative precision ignored */ 510 545 precision = 0; 511 546 } … … 514 549 515 550 switch (fmt[i++]) { 516 /** TODO:unimplemented qualifiers:551 /** @todo unimplemented qualifiers: 517 552 * t ptrdiff_t - ISO C 99 518 553 */ … … 535 570 break; 536 571 default: 537 qualifier = PrintfQualifierInt; /* default type */ 572 /* set default type */ 573 qualifier = PrintfQualifierInt; 538 574 --i; 539 575 } … … 543 579 switch (c = fmt[i]) { 544 580 545 546 547 581 /* 582 * String and character conversions. 583 */ 548 584 case 's': 549 if ((retval = print_string(va_arg(ap, char*), width, precision, flags, ps)) < 0) { 585 if ((retval = print_string(va_arg(ap, char*), 586 width, precision, flags, ps)) < 0) { 550 587 goto minus_out; 551 588 } … … 556 593 case 'c': 557 594 c = va_arg(ap, unsigned int); 558 if ((retval = print_char(c, width, flags, ps)) < 0) { 595 retval = print_char(c, width, flags, ps); 596 if (retval < 0) { 559 597 goto minus_out; 560 598 } … … 566 604 /* 567 605 * Integer values 568 */606 */ 569 607 case 'P': /* pointer */ 570 608 flags |= __PRINTF_FLAG_BIGCHARS; … … 595 633 goto next_char; 596 634 /* 597 * Bad formatting.598 */635 * Bad formatting. 636 */ 599 637 default: 600 /* Unknown format 601 * now, the j is index of '%' so we will 602 * print whole bad format sequence 638 /* 639 * Unknown format. Now, j is the index of '%', 640 * so we will print the whole bad format 641 * sequence. 603 642 */ 604 643 goto next_char; … … 606 645 607 646 608 /* Print integers */ 609 /* print number */ 647 /* Print integers */ 610 648 switch (qualifier) { 611 649 case PrintfQualifierByte: … … 627 665 case PrintfQualifierLongLong: 628 666 size = sizeof(unsigned long long); 629 number = (uint64_t)va_arg(ap, unsigned long long); 667 number = (uint64_t)va_arg(ap, 668 unsigned long long); 630 669 break; 631 670 case PrintfQualifierPointer: 632 671 size = sizeof(void *); 633 number = (uint64_t)(unsigned long)va_arg(ap, void *); 672 number = (uint64_t)(unsigned long)va_arg(ap, 673 void *); 634 674 break; 635 675 case PrintfQualifierSizeT: … … 643 683 644 684 if (flags & __PRINTF_FLAG_SIGNED) { 645 if (number & (0x1 << (size *8 - 1))) {685 if (number & (0x1 << (size * 8 - 1))) { 646 686 flags |= __PRINTF_FLAG_NEGATIVE; 647 687 … … 650 690 } else { 651 691 number = ~number; 652 number &= (~((0xFFFFFFFFFFFFFFFFll) << (size * 8))); 692 number &= 693 ~(0xFFFFFFFFFFFFFFFFll << 694 (size * 8)); 653 695 number++; 654 696 } … … 656 698 } 657 699 658 if ((retval = print_number(number, width, precision, base, flags, ps)) < 0 ) { 700 if ((retval = print_number(number, width, precision, 701 base, flags, ps)) < 0 ) { 659 702 goto minus_out; 660 } ;703 } 661 704 662 705 counter += retval; … … 669 712 670 713 if (i > j) { 671 if ((retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps)) < 0) { /* error */ 714 retval = printf_putnchars(&fmt[j], (size_t)(i - j), ps); 715 if (retval < 0) { /* error */ 672 716 goto minus_out; 673 717 }
Note:
See TracChangeset
for help on using the changeset viewer.