1 # $NetBSD: printf.sh,v 1.9 2022/05/24 20:50:20 andvar Exp $ 2 # 3 # Copyright (c) 2018 The NetBSD Foundation, Inc. 4 # All rights reserved. 5 # 6 # Redistribution and use in source and binary forms, with or without 7 # modification, are permitted provided that the following conditions 8 # are met: 9 # 1. Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # 2. Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # 15 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 # POSSIBILITY OF SUCH DAMAGE. 26 # 27 28 Running_under_ATF=false 29 test -n "${Atf_Shell}" && test -n "${Atf_Check}" && Running_under_ATF=true 30 31 Tests= 32 33 # create a test case: 34 # "$1" is basic test name, "$2" is description 35 define() 36 { 37 NAME=$1; shift 38 39 if $Running_under_ATF 40 then 41 eval "${NAME}_head() { set descr 'Tests printf: $*'; }" 42 eval "${NAME}_body() { ${NAME} ; }" 43 else 44 eval "TEST_${NAME}_MSG="'"$*"' 45 fi 46 47 Tests="${Tests} ${NAME}" 48 } 49 50 51 # 1st arg is printf format conversion specifier 52 # other args (if any) are args to that format 53 # returns success if that conversion specifier is supported, false otherwise 54 supported() 55 { 56 FMT="$1"; shift 57 58 case "$#" in 59 0) set -- 123;; # provide an arg for format to use 60 esac 61 62 (do_printf >/dev/null 2>&1 "%${FMT}" "$@") 63 } 64 65 LastErrorTest= 66 67 $Running_under_ATF || { 68 69 # Provide functions to emulate (roughly) what ATF gives us 70 # (that we actually use) 71 72 atf_skip() { 73 echo >&2 "${CurrentTest} skipped: ${MSG} $*" 74 } 75 atf_fail() { 76 if [ "${CurrentTest}" != "${LastErrorTest}" ] 77 then 78 echo >&2 "======== In Test ${CurrentTest}:" 79 LastErrorTest="${CurrentTest}" 80 fi 81 echo >&2 "${CurrentTest} FAIL: ${MSG} $*" 82 RVAL=1 83 } 84 atf_require_prog() { 85 # Just allow progs we want to run to be, or not be, found 86 return 0 87 } 88 } 89 90 # 1st arg is the result expected, remaining args are handed to do_printf 91 # to execute, fail if result does not match the expected result (treated 92 # as a sh pattern), or if do_printf fails 93 expect() 94 { 95 WANT="$1"; shift 96 negated=false 97 98 case "${WANT}" in 99 ('!') WANT="$1"; negated=true; shift;; 100 esac 101 102 RES="$( do_printf "$@" 2>&3 && echo X )" || atf_fail "$* ... Exit $?" 103 104 RES=${RES%X} # hack to defeat \n removal from $() output 105 106 if $negated 107 then 108 case "${RES}" in 109 (${WANT}) 110 atf_fail \ 111 "$* ... Expected anything but <<${WANT}>>, Received <<${RES}>>" 112 ;; 113 (*) 114 ;; 115 esac 116 else 117 case "${RES}" in 118 (${WANT}) 119 ;; 120 (*) 121 atf_fail "$* ... Expected <<${WANT}>> Received <<${RES}>>" 122 ;; 123 esac 124 fi 125 return 0 126 } 127 128 # a variant which allows for two possible results 129 # It would be nice to have just one function, and allow the pattern 130 # to contain alternatives ... but that would require use of eval 131 # to parse, and that then gets tricky with quoting the pattern. 132 # and we only ever need two (so far anyway), so this is easier... 133 expect2() 134 { 135 WANT1="$1"; shift 136 WANT2="$1"; shift 137 138 RES="$( do_printf "$@" 2>&3 && echo X )" || atf_fail "$* ... Exit $?" 139 140 RES=${RES%X} # hack to defeat \n removal from $() output 141 142 case "${RES}" in 143 (${WANT1} | ${WANT2}) 144 ;; 145 (*) 146 atf_fail \ 147 "$* ... Expected <<${WANT1}|${WANT2}>> Received <<${RES}>>" 148 ;; 149 esac 150 return 0 151 } 152 153 expect_fail() 154 { 155 WANT="$1"; shift # we do not really expect this, but ... 156 157 RES=$( do_printf "$@" 2>/dev/null && echo X ) && { 158 RES=${RES%X} 159 case "${RES}" in 160 (${WANT}) 161 atf_fail \ 162 "$* ... success${WANT:+ with expected <<${WANT}>>}" 163 ;; 164 ('') 165 atf_fail "$* ... success (without output)" 166 ;; 167 (*) 168 atf_fail "$* ... success with <<${RES}>> (not <<${WANT}>>)" 169 ;; 170 esac 171 172 RVAL=1 173 return 0 174 } 175 176 RES=$( do_printf "$@" 2>&1 >/dev/null ) 177 STAT=$? 178 test -z "${RES}" && 179 atf_fail "$* ... failed (${STAT}) without error message" 180 181 RES="$( do_printf "$@" 2>/dev/null || : ; echo X )" 182 RES=${RES%X} # hack to defeat \n removal from $() output 183 184 case "${RES}" in 185 (${WANT}) 186 # All is good, printf failed, sent a message to stderr 187 # and printed what it should to stdout 188 ;; 189 (*) 190 atf_fail \ 191 "$* ... should fail with <<${WANT}>> did exit(${STAT}) with <<${RES}>>" 192 ;; 193 esac 194 return 0 195 } 196 197 ########################################################################## 198 ########################################################################## 199 # 200 # Actual tests follow 201 # 202 ########################################################################## 203 ########################################################################## 204 205 basic() 206 { 207 setmsg basic 208 209 if (do_printf >/dev/null 2>&1) 210 then 211 atf_fail "with no args successful" 212 fi 213 if test -n "$( do_printf 2>/dev/null )" 214 then 215 atf_fail "with no args produces text on stdout" 216 fi 217 if test -z "$( do_printf 2>&1 )" 218 then 219 atf_fail "with no args no err/usage message" 220 fi 221 222 for A in - -- X 1 223 do 224 if (do_printf "%${A}%" >/dev/null 2>&1) 225 then 226 atf_fail "%${A}% successful" 227 fi 228 done 229 230 expect abcd abcd 231 expect % %% 232 expect xxx%yyy xxx%%yyy 233 expect -123 -123 234 235 # technically these are all unspecified, but the only rational thing 236 expect_fail '' %3% 237 expect_fail a a%.% 238 expect_fail '' '%*%b' # cannot continue after bad format 239 expect_fail a a%-%b # hence 'b' is not part of output 240 241 return $RVAL 242 } 243 define basic 'basic functionality' 244 245 format_escapes() 246 { 247 setmsg format_escapes 248 249 expect "${BSL}" '\\' 250 expect '?' '\\' # must be just 1 char 251 252 expect "${NL}" '\n' 253 expect " " '\t' # a literal <tab> in " " 254 255 expect "0" '\60' 256 expect "1" '\061' 257 expect "21" '\0621' 258 expect "${NL}" '\12' 259 expect "" '\1' 260 261 expect "" '\b' 262 expect "" '\f' 264 expect " " '\r' 266 expect "" '\a' 267 expect "" '\v' 269 270 expect "hello${NL}world${NL}!!${NL}" 'hello\nworld\n\a\a!!\n' 271 272 atf_require_prog wc 273 atf_require_prog od 274 atf_require_prog tr 275 276 for fmt in '\0' '\00' '\000' 277 do 278 RES=$(( $( do_printf "${fmt}" | wc -c ) )) 279 if [ "${RES}" -ne 1 ] 280 then 281 atf_fail "'${fmt}' output $RES bytes, expected 1" 282 elif [ $(( $( do_printf "${fmt}" | od -A n -to1 ) )) -ne 0 ] 283 then 284 RES="$( do_printf "${fmt}" | od -A n -to1 | tr -d ' ')" 285 atf_fail \ 286 "'${fmt}' output was '\\${RES}' should be '\\000'" 287 fi 288 done 289 290 # There are no expected failures here, as all other \Z 291 # sequences produce unspecified results -- anything is OK. 292 293 return $RVAL 294 } 295 define format_escapes "backslash escapes in format string" 296 297 s_strings() 298 { 299 setmsg s_strings 300 301 # The # and 0 flags produce undefined results (so don't test) 302 # The + and ' ' flags are ignored (only apply to signed conversions) 303 304 expect abcd %s abcd 305 expect ' a' %3s a 306 expect 'a ' %-3s a 307 expect abcd %3s abcd 308 expect abcd %-3s abcd 309 310 expect a %.1s abcd 311 expect ab %.2s abcd 312 expect abc %.3s abcd 313 expect abcd %.4s abcd 314 expect abcd %.5s abcd 315 expect abcd %.6s abcd 316 317 expect ' a' %4.1s abcd 318 expect ' ab' %4.2s abcd 319 expect ' abc' %4.3s abcd 320 expect abcd %4.4s abcd 321 expect abcd %4.5s abcd 322 expect abcd %4.6s abcd 323 324 expect ' a' %7.1s abcd 325 expect 'ab ' %-7.2s abcd 326 expect ' abc' %7.3s abcd 327 expect ' abcd' %7.4s abcd 328 expect 'abcd ' %-7.5s abcd 329 expect ' abcd' %7.6s abcd 330 331 expect 'aba a' %.2s%.1s%2.1s abcd abcd abcd 332 333 expect 123 %s 123 334 expect 1 %.1s 123 335 expect 12 %+.2s 123 336 expect -1 %+.2s -123 337 expect 12 '% .2s' 123 338 expect -1 '%+.2s' -123 339 340 expect '' %s '' 341 expect ' ' %1s '' 342 expect ' ' %6s '' 343 expect ' ' %2.1s '' 344 expect '' %.0s abcd 345 expect ' ' %2.0s abcd 346 expect ' ' %-3.0s abcd 347 348 # %s is just so boring! There are no possible failures to test. 349 350 return $RVAL 351 } 352 define s_strings "%s string output" 353 354 c_chars() 355 { 356 setmsg c_chars 357 358 expect a '%c' a 359 expect a '%c' abc 360 expect 'ad' '%c%c' abc def 361 expect '@ a@a @' "@%3c@%-3c@" a a 362 expect '@ a@a @' "@%2c@%-4c@" a a 363 364 # do not test with '' (null string) as operand to %c 365 # as whether that produces \0 or nothing is unspecified. 366 # (test NetBSD specific behaviour in NetBSD specific test) 367 368 return $RVAL 369 } 370 define c_chars '%c (character) format conversions' 371 372 d_decimal() 373 { 374 setmsg d_decimal 375 376 expect 0 '%d' 0 377 expect 1 '%d' 1 378 expect 999 '%d' 999 379 expect -77 '%d' -77 380 expect 51 '%d' 0x33 381 expect 51 '%d' 063 382 383 expect ' 2' '%4d' 2 384 expect '0002' '%04d' 2 385 expect '-002' '%04d' -2 386 expect '2 ' '%-4d' 2 387 expect ' 02' '%4.2d' 2 388 expect ' 22' '%4.2d' 22 389 expect ' 222' '%4.2d' 222 390 expect '2222' '%4.2d' 2222 391 expect '22222' '%4.2d' 22222 392 expect ' -02' '%4.2d' -2 393 expect '02 ' '%-4.2d' 2 394 expect '-02 ' '%-4.2d' -2 395 expect '22 ' '%-4.2d' 22 396 expect '222 ' '%-4.2d' 222 397 expect '2222' '%-4.2d' 2222 398 expect '22222' '%-4.2d' 22222 399 expect 1 '%.0d' 1 400 expect '' '%.0d' 0 401 expect '' '%.d' 0 402 expect ' ' '%3.d' 0 403 expect ' ' '%-4.d' 0 404 expect ' ' '%05.d' 0 405 406 expect 65 '%d' "'A" 407 expect 065 '%03d' "'A" 408 expect 49 '%d' "'1" 409 expect_fail 45 '%d' "'-1" 410 expect_fail 43 '%d' "'+1" 411 expect 00 '%.2d' "'" 412 413 expect 68 '%d' '"D' 414 expect 069 '%03d' '"E' 415 expect 51 '%d' '"3' 416 expect_fail 45 '%d' '"-3' 417 expect_fail 43 '%d' '"+3' 418 419 expect -1 '% d' -1 420 expect ' 1' '% d' 1 421 expect -1 '% 1d' -1 422 expect ' 1' '% 1d' 1 423 expect -1 '% 0d' -1 424 expect ' 1' '% 0d' 1 425 expect ' -1' '% 5d' -1 426 expect ' 1' '% 5d' 1 427 expect ' 01' '%0 3d' 1 428 expect '-01' '%0 3d' -1 429 expect ' 03' '% 4.2d' 3 430 expect ' -03' '% 4.2d' -3 431 432 expect -1 '%+d' -1 433 expect +1 '%+d' 1 434 expect ' -7' '%+3d' -7 435 expect ' +7' '%+3d' 7 436 expect ' -02' '%+4.2d' -2 437 expect ' +02' '%+4.2d' 2 438 expect '-09 ' '%-+4.2d' -9 439 expect '+09 ' '%+-4.2d' 9 440 441 # space flag is ignored if + is given, so same results as just above 442 expect -1 '%+ d' -1 443 expect +1 '%+ d' 1 444 expect ' -7' '%+ 3d' -7 445 expect ' +7' '%+ 3d' 7 446 expect ' -02' '%+ 4.2d' -2 447 expect ' +02' '%+ 4.2d' 2 448 expect '-09 ' '%- +4.2d' -9 449 expect '+09 ' '% +-4.2d' 9 450 451 expect_fail '0' %d junk 452 expect_fail '123' %d 123kb 453 expect_fail '15' %d 0xfooD 454 455 expect_fail '0 1 2' %d%2d%2d junk 1 2 456 expect_fail '3 1 2' %d%2d%2d 3 1+1 2 457 458 return $RVAL 459 } 460 define d_decimal '%d (decimal integer) conversions' 461 462 i_decimal() 463 { 464 setmsg i_decimal 465 466 supported i || { 467 atf_skip "%i conversion not supported" 468 return $RVAL 469 } 470 471 expect 0 '%i' 0 472 expect 1 '%i' 1 473 expect 999 '%i' 999 474 expect -77 '%i' -77 475 expect 51 '%i' 0x33 476 expect 51 '%i' 063 477 expect '02 ' '%-4.2i' 2 478 expect ' +02' '%+ 4.2i' 2 479 480 expect 0 '%i' '"' 481 482 expect_fail '0' %i x22 483 expect_fail '123' %i 123Mb 484 expect_fail '15' %i 0xfooD 485 486 return $RVAL 487 } 488 define i_decimal '%i (decimal integer) conversions' 489 490 u_unsigned() 491 { 492 setmsg u_unsigned 493 494 # Only tests of negative numbers are that we do not 495 # fail, and do not get a '-' in the result 496 497 # This is because the number of bits available is not defined 498 # so we cannot anticipate what value a negative number will 499 # produce when interpreted as unsigned (unlike hex and octal 500 # where we can at least examine the least significant bits) 501 502 expect 0 '%u' 0 503 expect 1 '%u' 1 504 expect 999 '%u' 999 505 expect 51 '%u' 0x33 506 expect 51 '%u' 063 507 508 expect ! '-*' '%u' -77 509 510 expect ' 2' '%4u' 2 511 expect '0002' '%04u' 2 512 expect '2 ' '%-4u' 2 513 expect ' 02' '%4.2u' 2 514 expect ' 22' '%4.2u' 22 515 expect ' 222' '%4.2u' 222 516 expect '2222' '%4.2u' 2222 517 expect '22222' '%4.2u' 22222 518 expect '02 ' '%-4.2u' 2 519 expect '22 ' '%-4.2u' 22 520 expect '222 ' '%-4.2u' 222 521 expect '2222' '%-4.2u' 2222 522 expect '22222' '%-4.2u' 22222 523 expect 1 '%.0u' 1 524 expect '' '%.0u' 0 525 expect '' '%.u' 0 526 expect ' ' '%3.u' 0 527 expect ' ' '%-4.u' 0 528 expect ' ' '%05.u' 0 529 530 expect 65 '%u' "'A" 531 expect 065 '%03u' "'A" 532 expect 49 '%u' "'1" 533 expect_fail 45 '%u' "'-1" 534 expect_fail 43 '%u' "'+1" 535 536 expect 68 '%u' '"D' 537 expect 069 '%03u' '"E' 538 expect 51 '%u' '"3' 539 expect_fail 45 '%u' '"-3' 540 expect_fail 43 '%u' '"+3' 541 542 # Note that the ' ' and '+' flags only apply to signed conversions 543 # so they should be simply ignored for '%u' 544 expect 1 '% u' 1 545 expect 1 '% 1u' 1 546 expect 1 '% 0u' 1 547 expect ' 1' '% 5u' 1 548 expect 001 '%0 3u' 1 549 expect ' 03' '% 4.2u' 3 550 551 expect ! '-*' '% u' -1 552 553 expect 1 '%+u' 1 554 expect ' 7' '%+3u' 7 555 expect ' 02' '%+4.2u' 2 556 expect '09 ' '%+-4.2u' 9 557 558 expect ! '-*' '%+u' -7 559 560 expect_fail '0' %u junk 561 expect_fail '123' %u 123kb 562 expect_fail '15' %u 0xfooD 563 564 expect_fail '0 1 2' %u%2u%2u junk 1 2 565 expect_fail '3 1 2' %u%2u%2u 3 1+1 2 566 567 return $RVAL 568 } 569 define u_unsigned '%u (unsigned decimal integer) conversions' 570 571 o_octal() 572 { 573 setmsg o_octal 574 575 expect 0 '%o' 0 576 expect 1 '%o' 1 577 expect 1747 '%o' 999 578 expect 63 '%o' 0x33 579 expect 63 '%o' 063 580 581 expect ' 2' '%4o' 2 582 expect '0002' '%04o' 2 583 expect '2 ' '%-4o' 2 584 expect ' 02' '%4.2o' 2 585 expect '02 ' '%-4.2o' 2 586 expect 1 '%.0o' 1 587 expect '' '%.0o' 0 588 589 expect ' 3' %3o 03 590 expect ' 33' %3o 033 591 expect '333' %3o 0333 592 expect '3333' %3o 03333 593 expect '33333' %3o 033333 594 595 expect '4 ' %-3o 04 596 expect '45 ' %-3o 045 597 expect '456' %-3o 0456 598 expect '4567' %-3o 04567 599 expect '45670' %-3o 045670 600 601 expect '04 ' %#-3o 04 602 expect '045' %-#3o 045 603 expect '0456' %#-3o 0456 604 expect '04567' %-#3o 04567 605 expect '045670' %#-3o 045670 606 607 expect 101 '%o' "'A" 608 expect 0101 '%04o' "'A" 609 expect 61 '%o' "'1" 610 expect_fail 55 '%o' "'-1" 611 expect_fail 53 '%o' "'+1" 612 613 expect 01747 '%#o' 999 614 expect ' 02' '%#4o' 2 615 expect '02 ' '%#-4.2o' 2 616 expect 0101 '%#o' "'A" 617 expect 0101 '%#04o' "'A" 618 expect 061 '%#o' "'1" 619 expect_fail 055 '%#o' "'-1" 620 expect_fail 053 '%#o' "'+1" 621 expect 063 '%#o' 063 622 623 # negative numbers are allowed, but printed as unsigned. 624 # Since we have no fixed integer width, we don't know 625 # how many upper 1 bits there will be, so only check the 626 # low 21 bits ... 627 expect '*7777777' '%o' -1 628 expect '*7777776' '%04o' -2 629 expect '*7777770' '%7o' -8 630 expect '0*7777700' '%#o' -0100 631 expect '*7777663' '%o' -77 632 633 return $RVAL 634 } 635 define o_octal '%o (octal integer) conversions' 636 637 x_hex() 638 { 639 setmsg x_hex 640 641 expect 0 '%x' 0 642 expect 1 '%x' 1 643 expect 3e7 '%x' 999 644 expect 33 '%x' 0x33 645 expect 33 '%x' 063 646 647 expect ' 2' '%4x' 2 648 expect '0002' '%04x' 2 649 expect '2 ' '%-4x' 2 650 expect ' 02' '%4.2x' 2 651 expect '02 ' '%-4.2x' 2 652 expect 1 '%.0x' 1 653 expect '' '%.0x' 0 654 655 expect 41 '%x' "'A" 656 expect 041 '%03x' "'A" 657 expect 31 '%x' "'1" 658 expect_fail 2d '%x' "'-1" 659 expect_fail 2b '%x' "'+1" 660 661 expect ' face ' '%5x ' 64206 662 663 # The 'alternate representation' (# flag) inserts 0x unless value==0 664 665 expect 0 %#x 0 666 expect 0x1 %#x 1 667 668 # We can also print negative numbers (treated as unsigned) 669 # but as there is no defined integer width for printf(1) 670 # we don't know how many F's in FFF...FFF for -1, so just 671 # validate the bottom 24 bits, and assume the rest will be OK. 672 # (tests above will fail if printf can't handle at least 32 bits) 673 674 expect '*ffffff' %x -1 675 expect '*fffff0' %x -16 676 expect '*fff00f' %x -4081 677 expect '*fff00d' %x -4083 678 expect '*fffabc' %x -1348 679 expect '*ff3502' %x -0xCAFE 680 681 expect_fail '0 1 2' %x%2x%2x junk 1 2 682 expect_fail '3 1 2' %x%2x%2x 3 1+1 2 683 684 return $RVAL 685 } 686 define x_hex '%x (hexadecimal output) conversions' 687 688 X_hex() 689 { 690 setmsg X_hex 691 692 # The only difference between %x and %X ix the case of 693 # the alpha digits, so just do minimal testing of that... 694 695 expect 3E7 %X 999 696 expect_fail 2D %X "'-1" 697 expect_fail 2B %X "'+1" 698 expect ' FACE ' '%5X ' 64206 699 expect DEADBEEF %X 3735928559 700 701 expect 1234FEDC %X 0x1234fedc 702 703 expect '*FFCAFE' %X -13570 704 expect '*FFFFFE' %X -2 705 706 return $RVAL 707 } 708 define X_hex '%X (hexadecimal output) conversions' 709 710 f_floats() 711 { 712 setmsg f_floats 713 714 supported f || { 715 atf_skip "%f conversion not supported" 716 return $RVAL 717 } 718 719 expect 0.000000 %f 0 720 expect 1.000000 %f 1 721 expect 1.500000 %f 1.5 722 expect -1.000000 %f -1 723 expect -1.500000 %f -1.5 724 725 expect 44.000000 %f 44 726 expect -43.000000 %f -43 727 expect '3.33333?' %f 3.333333333333333 728 expect '0.78539?' %f .7853981633974483 729 expect '0.00012?' %f .000123456789 730 expect '1234.56789?' %f 1234.56789 731 732 expect 0 %.0f 0 733 expect 1 %.0f 1 734 expect 1. %#.0f 1.1 735 expect 0. %#.0f 0 736 expect 1. %#.0f 1 737 expect 1. %#.0f 1.2 738 739 expect 0.0 %.1f 0 740 expect 1.0 %.1f 1 741 expect 1.1 %#.1f 1.1 742 expect 0.0 %#.1f 0 743 expect 1.2 %#.1f 1.2 744 745 expect ' 0.0' %6.1f 0 746 expect ' 1.0' %6.1f 1 747 expect ' -1.0' %6.1f -1 748 749 expect '0000.0' %06.1f 0 750 expect '0001.0' %06.1f 1 751 expect '-001.0' %06.1f -1 752 753 expect ' +0.0' %+6.1f 0 754 expect ' +1.0' %+6.1f 1 755 expect ' -1.0' %+6.1f -1 756 757 expect ' 0.0' '% 6.1f' 0 758 expect ' 1.0' '% 6.1f' 1 759 expect ' -1.0' '% 6.1f' -1 760 761 expect ' 000.0' '%0 6.1f' 0 762 expect ' 001.0' '% 06.1f' 1 763 expect '-001.0' '%0 6.1f' -1 764 765 expect '+000.0' '%0+6.1f' 0 766 expect '+001.0' '%+06.1f' 1 767 expect '-001.0' '%0+6.1f' -1 768 769 expect '0000000.00' %010.2f 0 770 expect '-000009.00' %010.2f -9 771 772 expect '0.0 ' %-10.1f 0 773 expect '1.0 ' %-10.1f 1 774 expect '-1.0 ' %-10.1f -1 775 776 expect '0.00 ' %-10.2f 0 777 expect '-9.00 ' %-10.2f -9 778 779 expect '0.0 ' %-010.1f 0 780 expect '1.0 ' %-010.1f 1 781 expect '-1.0 ' %-010.1f -1 782 783 expect '0.00 ' %-6.2f 0 784 expect '-9.00 ' %-6.2f -9 785 786 expect '0.00 ' %-010.2f 0 787 expect '-9.00 ' %-010.2f -9 788 789 expect ' 0' %7.0f 0 790 expect '1 ' %-7.0f 1 791 expect ' 0.' %#7.0f 0 792 expect ' 1.' %#7.0f 1 793 expect ' 1.' %#7.0f 1.1 794 expect ' 1.' %#7.0f 1.2 795 expect ' -1.' %#7.0f -1.2 796 expect '1. ' %-#7.0f 1.1 797 expect '0. ' %#-7.0f 0 798 expect '1. ' %-#7.0f 1 799 expect '1. ' %#-7.0f 1.2 800 expect '-1. ' %#-7.0f -1.2 801 expect ' +0' %+7.0f 0 802 expect '+1 ' %-+7.0f 1 803 expect ' +1.' %+#7.0f 1.1 804 expect ' +0.' %#+7.0f 0 805 expect ' +1.' %+#7.0f 1 806 expect ' +1.' %#+7.0f 1.2 807 expect ' -1.' %#+7.0f -1.2 808 expect ' 0' '% 7.0f' 0 809 expect ' 1 ' '%- 7.0f' 1 810 expect '-1 ' '%- 7.0f' -1 811 expect ' 1.' '% #7.0f' 1.1 812 expect ' 0.' '%# 7.0f' 0 813 expect ' 1.' '% #7.0f' 1 814 expect ' 1.' '%# 7.0f' 1.2 815 expect ' -1.' '%# 7.0f' -1.2 816 817 expect2 inf infinity %f infinity 818 expect2 inf infinity %f Infinity 819 expect2 inf infinity %f INF 820 expect2 -inf -infinity %f -INF 821 expect2 ' inf' infinity %5f INF 822 expect2 ' inf' ' infinity' %9.4f INF 823 expect2 'inf ' 'infinity ' %-11.1f INF 824 expect2 ' inf' infinity %05f INF 825 expect2 ' inf' infinity %05f +INF 826 expect2 ' -inf' -infinity %05f -INF 827 expect2 'inf ' infinity %-5f INF 828 expect2 ' +inf' +infinity %+5f INF 829 expect2 ' +inf' +infinity %+5f +INF 830 expect2 ' -inf' -infinity %+5f -INF 831 expect2 ' inf' infinity '% 5f' INF 832 expect2 ' inf' infinity '% 5f' +INF 833 expect2 ' -inf' -infinity '% 5f' -INF 834 835 expect2 nan 'nan(*)' %f NaN 836 expect2 nan 'nan(*)' %f -NaN 837 expect2 ' nan' 'nan(*)' %5f nan 838 expect2 'nan ' 'nan(*)' %-5f NAN 839 840 expect_fail '0.0 1.0 2.0' %.1f%4.1f%4.1f junk 1 2 841 expect_fail '3.0 1.0 2.0' %.1f%4.1f%4.1f 3 1+1 2 842 843 return $RVAL 844 } 845 define f_floats '%f (floating) conversions' 846 847 F_floats() 848 { 849 setmsg F_floats 850 851 # The only difference between %f and %f is how Inf and NaN 852 # are printed ... so just test a couple of those and 853 # a couple of the others above (to verify nothing else changes) 854 855 supported F || { 856 atf_skip "%F conversion not supported" 857 return $RVAL 858 } 859 860 expect '0.78539?' %F .7853981633974483 861 expect '0.00012?' %F .000123456789 862 expect '1234.56789?' %F 1234.56789 863 864 expect2 INF INFINITY %F infinity 865 expect2 -INF -INFINITY %F -INFINITY 866 expect2 NAN 'NAN(*)' %F NaN 867 868 return $RVAL 869 } 870 define F_floats '%F (floating) conversions' 871 872 e_floats() 873 { 874 setmsg e_floats 875 876 supported e || { 877 atf_skip "%e conversion not supported" 878 return $RVAL 879 } 880 881 expect 0.000000e+00 %e 0 882 expect 1.000000e+00 %e 1 883 expect 1.500000e+00 %e 1.5 884 expect -1.000000e+00 %e -1 885 expect -1.500000e+00 %e -1.5 886 887 expect 4.400000e+01 %e 44 888 expect -4.300000e+01 %e -43 889 expect '3.33333?e+00' %e 3.333333333333333 890 expect '7.85398?e-01' %e .7853981633974483 891 expect '1.23456?e-04' %e .000123456789 892 expect '1.23456?e+03' %e 1234.56789 893 894 expect 0e+00 %.0e 0 895 expect 1e+00 %.0e 1 896 expect 1.e+00 %#.0e 1.1 897 expect 0.e+00 %#.0e 0 898 expect 1.e+00 %#.0e 1 899 expect 1.e+00 %#.0e 1.2 900 901 expect 0.0e+00 %.1e 0 902 expect 1.0e+00 %.1e 1 903 expect 1.1e+00 %#.1e 1.1 904 expect 0.0e+00 %#.1e 0 905 expect 1.2e+00 %#.1e 1.2 906 907 expect ' 0.0e+00' %10.1e 0 908 expect ' 1.0e+00' %10.1e 1 909 expect ' -1.0e+00' %10.1e -1 910 911 expect '0000.0e+00' %010.1e 0 912 expect '0001.0e+00' %010.1e 1 913 expect '-001.0e+00' %010.1e -1 914 915 expect ' +0.0e+00' %+10.1e 0 916 expect ' +1.0e+00' %+10.1e 1 917 expect ' -1.0e+00' %+10.1e -1 918 919 expect ' 0.0e+00' '% 10.1e' 0 920 expect ' 1.0e+00' '% 10.1e' 1 921 expect ' -1.0e+00' '% 10.1e' -1 922 923 expect ' 000.0e+00' '%0 10.1e' 0 924 expect ' 001.0e+00' '% 010.1e' 1 925 expect '-001.0e+00' '%0 10.1e' -1 926 927 expect '000.00e+00' %010.2e 0 928 expect '-09.00e+00' %010.2e -9 929 930 expect '0.0e+00 ' %-10.1e 0 931 expect '1.0e+00 ' %-10.1e 1 932 expect '-1.0e+00 ' %-10.1e -1 933 934 expect '+0.0e+00 ' %-+10.1e 0 935 expect '+1.0e+00 ' %+-10.1e 1 936 expect '-1.0e+00 ' %+-10.1e -1 937 938 expect ' +0.0e+00' '%+ 10.1e' 0 939 expect ' +1.0e+00' '% +10.1e' 1 940 expect ' -1.0e+00' '%+ 10.1e' -1 941 942 expect '0.00e+00 ' %-10.2e 0 943 expect '-9.00e+00 ' %-10.2e -9 944 945 expect '0.0e+00 ' %-010.1e 0 946 expect '1.0e+00 ' %0-10.1e 1 947 expect '-1.0e+00 ' %-010.1e -1 948 949 expect '0.00e+00 ' %-010.2e 0 950 expect '-9.00e+00 ' %-010.2e -9 951 952 expect ' 0e+00' %7.0e 0 953 expect '1e+00 ' %-7.0e 1 954 expect ' 1.e+00' %#7.0e 1.1 955 expect ' 0.e+00' %#7.0e 0 956 expect ' 1.e+00' %#7.0e 1 957 expect ' 1.e+00' %#7.0e 1.2 958 expect '-1.e+00' %#7.0e -1.2 959 expect '1.e+00 ' %-#7.0e 1.1 960 expect '0.e+00 ' %#-7.0e 0 961 expect '1.e+00 ' %-#7.0e 1 962 expect '1.e+00 ' %#-7.0e 1.2 963 expect '-1.e+00' %#-7.0e -1.2 964 expect ' +0e+00' %+7.0e 0 965 expect '+1e+00 ' %-+7.0e 1 966 expect '+1.e+00' %+#7.0e 1.1 967 expect '+0.e+00' %#+7.0e 0 968 expect '+1.e+00' %+#7.0e 1 969 expect '+1.e+00' %#+7.0e 1.2 970 expect '-1.e+00' %#+7.0e -1.2 971 expect ' 0e+00' '% 7.0e' 0 972 expect ' 1e+00 ' '%- 7.0e' 1 973 expect '-1e+00 ' '%- 7.0e' -1 974 expect ' 1.e+00' '% #7.0e' 1.1 975 expect ' 0.e+00' '%# 7.0e' 0 976 expect ' 1.e+00' '% #7.0e' 1 977 expect ' 1.e+00' '%# 7.0e' 1.2 978 expect '-1.e+00' '%# 7.0e' -1.2 979 980 expect2 inf infinity %e inf 981 expect2 inf infinity %e Infinity 982 expect2 inf infinity %e INF 983 expect2 -inf -infinity %e -INF 984 expect2 ' inf' -infinity %5e INF 985 expect2 ' inf' -infinity %9.4e INF 986 expect2 ' inf' infinity %05e INF 987 expect2 ' inf' infinity %05e +INF 988 expect2 ' -inf' -infinity %05e -INF 989 expect2 'inf ' infinity %-5e INF 990 expect2 ' +inf' +infinity %+5e INF 991 expect2 ' +inf' +infinity %+5e +INF 992 expect2 ' -inf' -infinity %+5e -INF 993 expect2 ' inf' infinity '% 5e' INF 994 expect2 ' inf' infinity '% 5e' +INF 995 expect2 ' -inf' -infinity '% 5e' -INF 996 997 expect2 nan 'nan(*)' %e NaN 998 expect2 nan 'nan(*)' %e -NaN 999 expect2 ' nan' 'nan(*)' %5e nan 1000 expect2 'nan ' 'nan(*)' %-5e NAN 1001 1002 expect_fail 0.000000e+00 '%e' NOT-E 1003 expect_fail 1.200000e+00 '%e' 1.2Gb 1004 1005 return $RVAL 1006 } 1007 define e_floats "%e floating point conversions" 1008 1009 E_floats() 1010 { 1011 setmsg E_floats 1012 1013 supported E || { 1014 atf_skip "%E conversion not supported" 1015 return $RVAL 1016 } 1017 1018 # don't bother duplicating all the above, the only differences 1019 # should be 'E' instead of 'e', and INF/NAN (for inf/nan) 1020 # so just pick a few... 1021 1022 expect 0.000000E+00 %E 0 1023 expect -4.300000E+01 %E -43 1024 expect 1E+00 %.0E 1 1025 expect 1.E+00 %#.0E 1 1026 expect '-9.00E+00 ' %-010.2E -9 1027 expect2 INF INFINITY %E InFinity 1028 expect2 NAN 'NAN(*)' %E NaN 1029 1030 return $RVAL 1031 } 1032 define E_floats "%E floating point conversions" 1033 1034 1035 g_floats() 1036 { 1037 setmsg g_floats 1038 1039 supported g || { 1040 atf_skip "%g conversion not supported" 1041 return $RVAL 1042 } 1043 1044 # for a value writtem in %e format, which has an exponent of x 1045 # then %.Pg will produce 'f' format if x >= -4, and P > x, 1046 # otherwise it produces 'e' format. 1047 # When 'f' is used, the precision associated is P-x-1 1048 # when 'e' is used, the precision is P-1 1049 1050 # then trailing 0's are deleted (unless # flag is present) 1051 1052 # since we have other tests for 'f' and 'e' formats, rather 1053 # than testing lots of random numbers, instead test that the 1054 # switchover between 'f' and 'e' works properly. 1055 1056 expect 1 %.1g 1 # p = 1, x = 0 : %.0f 1057 expect 0.5 %.1g 0.5 # p = 1, x = -1: %.1f 1058 expect 1 %.2g 1 # p = 2, x = 0 : %.1f 1059 expect 0.5 %.2g 0.5 # p = 2, x = -1: %.2f 1060 1061 expect 1 %g 1 # p = 6, x = 0 : %.5f 1062 expect -0.5 %g -0.5 # p = 6, x = -1: %.6f 1063 1064 expect 0.001234 %.4g 0.001234 # p= 4, x = -3: %.6f 1065 1066 expect 9999 %.4g 9999 # p = 4, x = 3 : %.0f 1067 expect 9999 %.5g 9999 # p = 5, x = 3 : %.1f 1068 1069 expect 1. %#.1g 1 # p = 1, x = 0 : %.0f 1070 expect 0.5 %#.1g 0.5 # p = 1, x = -1: %.1f 1071 expect 1.0 %#.2g 1 # p = 2, x = 0 : %.1f 1072 expect 0.50 %#.2g 0.5 # p = 2, x = -1: %.2f 1073 1074 expect 1.00000 %#g 1 # p = 6, x = 0 : %.5f 1075 expect -0.500000 %#g -0.5 # p = 6, x = -1: %.6f 1076 1077 expect 0.001234 %#.4g 0.001234 # p= 4, x = -3 : %.6f 1078 1079 expect 9999. %#.4g 9999 # p = 4, x = 3 : %.0f 1080 expect 9999.0 %#.5g 9999 # p = 5, x = 3 : %.1f 1081 1082 expect 4.4?e+03 %.3g 4444 # p = 3, x = 3 : %.2e 1083 expect 1.2e-05 %.2g 0.000012 # p = 2, x = -5: %.1e 1084 1085 expect 1e+10 %g 10000000000 1086 expect 1e+10 %g 1e10 1087 expect 1e+10 %g 1e+10 1088 expect 1e-10 %g 1e-10 1089 expect 10000000000 %.11g 10000000000 1090 expect 10000000000. %#.11g 10000000000 1091 expect 1e+99 %g 1e99 1092 expect 1e+100 %g 1e100 1093 expect 1e-100 %g 1e-100 1094 1095 expect2 inf infinity %g Infinity 1096 expect2 -inf -infinity %g -INF 1097 expect2 nan 'nan(*)' %g NaN 1098 1099 return $RVAL 1100 } 1101 define g_floats '%g (floating) conversions' 1102 1103 G_floats() 1104 { 1105 setmsg G_floats 1106 1107 supported G || { 1108 atf_skip "%G conversion not supported" 1109 return $RVAL 1110 } 1111 1112 # 'G' uses 'F' or 'E' instead or 'f' or 'e'. 1113 1114 # F is different from f only for INF/inf NAN/nan which there is 1115 # no point testing here (those simply use F/f format, tested there. 1116 # E is different for those, and also uses 'E' for the exponent 1117 # That is the only thing to test, so ... 1118 1119 expect 1.2E-05 %.2G 0.000012 # p = 2, x = -5: $.1e 1120 1121 expect2 INF INFINITY %G Infinity 1122 expect2 -INF -INFINITY %G -INF 1123 expect2 NAN 'NAN(*)' %G NaN 1124 1125 return $RVAL 1126 } 1127 define G_floats '%G (floating) conversions' 1128 1129 # It is difficult to test correct results from the %a conversions, 1130 # as they depend upon the underlying floating point format (not 1131 # necessarily IEEE) and other factors chosen by the implementation, 1132 # eg: the (floating) number 1 could be 0x8p-3 0x4p-2 0x1p-1 even 1133 # assuming IEEE formats wnen using %.0a. But we can test 0 1134 a_floats() 1135 { 1136 setmsg a_floats 1137 1138 supported a || { 1139 atf_skip "%a conversion not supported" 1140 return $RVAL 1141 } 1142 1143 expect 0x0p+0 '%.0a' 0 1144 expect 0x0.p+0 '%#.0a' 0 1145 expect 0x0.000p+0 '%.3a' 0 1146 expect '0x?.*p+*' '%a' 123 1147 expect '0x?.*p-*' '%a' 0.123 1148 1149 # We can check that the %a result can be used as input to %f 1150 # and obtain the original value (nb: input must be in %.4f format) 1151 1152 for VAL in 1.0000 2.0000 3.0000 4.0000 0.5000 0.1000 1000.0000 \ 1153 777777.0000 0.1234 -1.0000 -0.2500 -123.4567 1154 do 1155 A_STRING=$( do_printf '%a' "${VAL}" 2>&3 ) 1156 1157 expect "${VAL}" "%.4f" "${A_STRING}" 1158 done 1159 1160 expect_fail 0x0p+0 %a trash 1161 expect_fail 0x0.p+0 %#a trash 1162 expect_fail X0x0p+0Y X%aY trash 1163 expect_fail 0x0p+00x0p+0 %a%a trash garbage 1164 1165 return $RVAL 1166 } 1167 define a_floats '%a floating conversion' 1168 1169 A_floats() 1170 { 1171 setmsg A_floats 1172 1173 supported A || { 1174 atf_skip "%A conversion not supported" 1175 return $RVAL 1176 } 1177 1178 expect 0X0P+0 '%.0A' 0 1179 expect 0X0.P+0 '%#.0A' 0 1180 expect 0X0.000P+0 '%.3A' 0 1181 expect '0X?.*P+*' '%A' 123 1182 expect '0X?.*P-*' '%A' 0.123 1183 1184 for VAL in 1.0000 2.0000 3.0000 4.0000 0.5000 0.1000 1000.0000 \ 1185 777777.0000 0.1234 -1.0000 -0.2500 -123.4567 1186 do 1187 A_STRING=$( do_printf '%A' "${VAL}" 2>&3 ) 1188 1189 expect "${VAL}" "%.4f" "${A_STRING}" 1190 done 1191 1192 expect_fail 0X0P+0 %A trash 1193 expect_fail 0X0.P+0 %#A trash 1194 expect_fail X0X0P+0X X%AX trash 1195 expect_fail 0X0P+00X0P+0 %A%A trash garbage 1196 1197 return $RVAL 1198 } 1199 define A_floats '%A floating conversion' 1200 1201 missing_args() 1202 { 1203 setmsg missing_args 1204 1205 # Note: missing string arg is replaced by "" and behaviour 1206 # of %c is either nothing or '\0' in that case, so avoid 1207 # testing missing arg for %c. 1208 1209 1210 expect '' %s 1211 expect '' %b 1212 expect 0 %d 1213 expect 0 %o 1214 expect 0 %x 1215 expect 0 %#o 1216 expect 0 %#X 1217 1218 expect 'xxxyyyzzz' '%syyy%szzz' xxx 1219 expect 'a=1, b=0' 'a=%d, b=%d' 1 1220 1221 expect 000000 %d%u%i%x%o%X 1222 expect 437000 %d%u%i%x%o%X 4 3 7 1223 1224 if supported f 1225 then 1226 expect 0.000000 %f 1227 expect 'x=0.0' '%s=%.1f' x 1228 fi 1229 1230 return $RVAL 1231 } 1232 define missing_args "format string when there are no more args" 1233 1234 repeated_format() 1235 { 1236 setmsg repeated_format 1237 1238 expect abcd %s a b c d 1239 expect 1234 %d 1 2 3 4 1240 expect ' 1 2 3 4' %2d 1 2 3 4 1241 expect abcd %.1s aaa bbb ccc ddd 1242 expect ' a=1 b=2 c=3' %2s=%d a 1 b 2 c 3 1243 expect "hello${NL}world${NL}" '%s\n' hello world 1244 expect "a${NL}b${NL}c${NL}d${NL}" '%.1s\n' aaa bbb ccc ddd 1245 1246 expect "\ 1247 1.00"' 1248 9.75 1249 -3.00 1250 999.99 1251 -101.01'"${NL}" '%7.2f\n' 1 9.75 -3 999.99 -101.01 1252 1253 expect " 1 010x1${NL} 220260x16${NL} 9201340x5c${NL}" \ 1254 '%3d%#3o%#3x\n' 1 1 1 22 22 22 92 92 92 1255 1256 expect ' 1 2 3 4 5' %2d 1 2 3 4 5 1257 expect ' 1 2 3 4 5 0' %2d%2d%2d 1 2 3 4 5 1258 1259 1260 return $RVAL 1261 } 1262 define repeated_format 'format string is reused until all args used' 1263 1264 b_SysV_echo() 1265 { 1266 setmsg b_SysV_echo 1267 1268 # Basic formatting 1269 1270 expect '' %b '' 1271 expect '' %.0b abcd 1272 expect abcd %b abcd 1273 expect ' ab' %3.2b abcd 1274 expect 'a ' %-3.1b abcd 1275 expect ' ' %3.0b abcd 1276 1277 # The simple stuff. nb: no \c tests, it has a whole test case to itself 1278 1279 expect "${BSL} ${NL}" %b '\\\t\n' 1280 expect ' ' %b '\a\v\r\f\b' 1284 expect 'ABC' %b '\01A\002\0102\0003C' 1285 expect "a${NL}b${NL}" %b 'a\nb\n' 1286 1287 # and unlikely to occur IRL 1288 expect " ab " %7.4b 'ab\r\bxy\t\t\n' 1290 expect "111 " %-6.3b '\00611\061\01\n\t\n' 1291 1292 # and last, that pesky \0 1293 1294 atf_require_prog wc 1295 atf_require_prog sed 1296 1297 for fmt in '\0' '\00' '\000' '\0000' 1298 do 1299 if [ $( do_printf %b "${fmt}" | wc -c ) -ne 1 ] 1300 then 1301 atf_fail \ 1302 "%b '${fmt}' did not output exactly 1 character (byte)" 1303 elif [ $(( $( do_printf %b "${fmt}" | od -A n -to1 ) )) -ne 0 ] 1304 then 1305 atf_require_prog od 1306 atf_require_prog tr 1307 1308 RES="$(do_printf %b "${fmt}" | od -An -to1 | tr -d ' ')" 1309 atf_fail \ 1310 "%b '${fmt}' output was '\\${RES}' should be '\\000'" 1311 fi 1312 1313 for xt in "x${fmt}" "${fmt}q" "x${fmt}q" "${fmt}\\0" \ 1314 "${fmt}|\\0|\\0|" "${fmt}${fmt}" "+${fmt}-${fmt}*" 1315 do 1316 # nb: we "know" here that the only \'s are \0's 1317 # nb: not do_printf, we are not testing ... 1318 bsl=$( printf %s "${xt}" | sed -e 's/\\00*/X/g' ) 1319 xl=${#bsl} 1320 1321 RES=$(( $( do_printf %b "${xt}" | wc -c ) )) 1322 1323 if [ "${RES}" -ne "${xl}" ] 1324 then 1325 atf_fail \ 1326 "%b '${xt}' output ${RES} chars, expected ${xl}" 1327 fi 1328 done 1329 1330 test ${#fmt} -lt 5 && continue 1331 1332 if [ $( do_printf %b "${fmt}1" | wc -c ) -ne 2 ] 1333 then 1334 atf_fail \ 1335 "%b '${fmt}1' did not output exactly 2 characters" 1336 fi 1337 done 1338 1339 return $RVAL 1340 } 1341 define b_SysV_echo '%b format - emulate SysV echo escapes' 1342 1343 b_SysV_echo_backslash_c() 1344 { 1345 setmsg b_SysV_echo_backslash_c 1346 1347 # test \c in arg to printf %b .. causes instant death... 1348 1349 expect ab %b 'ab\cdef' 1350 expect ab a%bc 'b\cd' 1351 1352 expect abcd %s%c%x%b a bcd 12 'd\c' 1353 expect ad %.1s%x%b%c%x all 13 '\cars' cost 12 1354 expect "a${NL}b" '%b\n' a 'b\c' d '\ce' 1355 1356 # This is undefined, though would be nice if we could rely upon it 1357 # expect "abcd" %.1b 'a\c' 'b\c' 'c\c' 'd\c' '\c' e 1358 1359 # Check for interference from one instance of execution of 1360 # a builtin printf execution to another 1361 # (this makes no sense to test for standalone printf, and for which 1362 # the tests don't handle ';' magic args, so this would not work) 1363 if $BUILTIN_TEST 1364 then 1365 expect abcdefjklmno %s%b%s abc 'def\c' ghi ';' %s%s jkl mno 1366 fi 1367 1368 return $RVAL 1369 } 1370 define b_SysV_echo_backslash_c 'Use of \c in arg to %b format' 1371 1372 indirect_width() 1373 { 1374 setmsg indirect_width 1375 1376 supported '*d' 5 123 || { 1377 atf_skip "%*d not supported (indirect field width)" 1378 return $RVAL 1379 } 1380 1381 lpad= rpad= zpad= 1382 for i in 1 2 3 4 5 6 7 8 9 10 1383 do 1384 expect "${lpad}7" '%*d' "$i" 7 1385 expect "6${rpad}" '%-*d' "$i" 6 1386 expect "${zpad}5" '%0*d' "$i" 5 1387 1388 lpad="${lpad} " 1389 rpad="${rpad} " 1390 zpad="${zpad}0" 1391 done 1392 1393 return $RVAL 1394 } 1395 define indirect_width "using * to get field width from arg" 1396 1397 indirect_precision() 1398 { 1399 setmsg indirect_precision 1400 1401 supported '.*d' 5 123 || { 1402 atf_skip "%.*d not supported (indirect precision)" 1403 return $RVAL 1404 } 1405 1406 res= zpad=. 1407 for i in 0 1 2 3 4 5 6 7 8 9 1408 do 1409 expect "${res}" '%.*s' "$i" aaaaaaaaaaaaaaaa 1410 res="${res}a" 1411 1412 expect "3${zpad}" '%#.*f' "$i" 3 1413 zpad="${zpad}0" 1414 done 1415 1416 return $RVAL 1417 } 1418 define indirect_precision 'Using .* as to get precision from arg' 1419 1420 indirect_both() 1421 { 1422 setmsg indirect_both 1423 1424 supported '*.*d' 5 2 123 || { 1425 atf_skip "%*.*d not supported (indirect width & precision)" 1426 return $RVAL 1427 } 1428 1429 res= 1430 for i in 1 2 3 4 5 6 7 8 1431 do 1432 res="${res}z" 1433 expect " ${res}" '%*.*s' $(( $i + 2 )) "$i" zzzzzzzzzzz 1434 done 1435 1436 expect ' ab: 9: 1.20' "%*.*s:%*d:%*.*f" 4 2 abcde 3 9 5 2 1.2 1437 1438 return $RVAL 1439 } 1440 define indirect_both 'Using *.* as to get width & precision from args' 1441 1442 q_quoting() 1443 { 1444 setmsg q_quoting 1445 1446 if ! supported q 1447 then 1448 atf_skip '%q format not supported' 1449 return $RVAL 1450 fi 1451 1452 # Testing quoting isn't as straightforward as many of the 1453 # others, as there is no specific form in which the output 1454 # is required to appear 1455 1456 # Instead, we will apply %q to various strings, and then 1457 # process them again in this shell, and see if the string 1458 # we get back is the same as the string we started with. 1459 1460 for string in \ 1461 abcd \ 1462 'hello world' \ 1463 '# a comment ....' \ 1464 '' \ 1465 'a* b* c*' \ 1466 'ls | wc' \ 1467 '[<> # | { ~.** } $@]' \ 1468 '( who & echo $! )' 1469 do 1470 QUOTED="$(do_printf %q "$string")" 1471 1472 eval "RES=${QUOTED}" 1473 1474 if [ "${RES}" != "${string}" ] 1475 then 1476 atf_fail \ 1477 "%q <<${string}>> as <<${QUOTED}>> makes <<${RES}>>" 1478 continue 1479 fi 1480 1481 QUOTED="$(do_printf %-32q "$string")" 1482 1483 if [ ${#QUOTED} -lt 32 ] 1484 then 1485 atf-fail \ 1486 "%-32q <<${string}>> short result (${#QUOTED}) <<${QUOTED}>>" 1487 1488 fi 1489 1490 eval "RES=${QUOTED}" 1491 if [ "${RES}" != "${string}" ] 1492 then 1493 atf_fail \ 1494 "%-32q <<${string}>> as <<${QUOTED}>> makes <<${RES}>>" 1495 continue 1496 fi 1497 done 1498 1499 # %q is a variant of %s, but using field width (except as above), 1500 # and especially precision makes no sense, and is implrmented so 1501 # badly that testing it would be hopeless. Other flags do nothing. 1502 1503 return $RVAL 1504 } 1505 define q_quoting '%q quote string suitably for sh processing' 1506 1507 NetBSD_extensions() 1508 { 1509 setmsg NetBSD_extensions 1510 1511 if $BUILTIN_TEST 1512 then 1513 # what matters if $TEST_SH is a NetBSD sh 1514 ${TEST_SH} -c 'test -n "$NETBSD_SHELL"' || { 1515 atf_skip \ 1516 "- ${TEST_SH%% *} is not a (modern) NetBSD shell" 1517 return $RVAL 1518 } 1519 fi 1520 if ! supported '*.*%%_._' 78 66 1521 then 1522 if $BUILTIN_TEST 1523 then 1524 atf_skip \ 1525 "- ${TEST_SH%% *} is not a (modern enough) NetBSD shell" 1526 else 1527 atf_skip "- ${PRINTF} is not a (modern) NetBSD printf" 1528 fi 1529 return $RVAL 1530 fi 1531 1532 # Even in the most modern NetBSD printf the data length modifiers 1533 # might not be supported. 1534 1535 if supported zd 1536 then 1537 expect 88888 %jd 88888 1538 expect 88888 %ld 88888 1539 expect 88888 %lld 88888 1540 expect 88888 %Ld 88888 1541 expect 88888 %td 88888 1542 expect 88888 %zd 88888 1543 1544 expect 23352 %hd 88888 1545 expect 56 %hhd 88888 1546 1547 expect 300000 %jd 300000 1548 expect 300000 %Ld 300000 1549 expect -27680 %hd 300000 1550 expect -32 %hhd 300000 1551 1552 expect 15b38 %jx 88888 1553 expect 5b38 %hx 88888 1554 expect 38 %hhx 88888 1555 1556 expect 93e0 %hx 300000 1557 expect e0 %hhx 300000 1558 1559 # to test modifiers attached to floats we'd need to 1560 # verify float support, so don't bother... 1561 fi 1562 1563 expect 6.500000e+01 '%e' "'A" 1564 expect 6.5e+01 '%.1e' "'A" 1565 expect 5e+01 '%.0e' "'1" 1566 expect_fail 4.50e+01 '%.2e' "'-1" 1567 expect_fail 4.300e+01 '%.3e' "'+1" 1568 expect 99.000000 '%f' '"c' 1569 expect 97 '%g' '"a' 1570 1571 # NetBSD (non-POSIX) format escape extensions 1572 expect '' '\e' 1573 expect '' '\E' 1574 expect '' '\e\E' 1575 1576 # NetBSD (non-POSIX) %b string escape extensions 1577 expect '' %b '\^A\^a\1' 1578 expect 'S4=X' %b '\1234\75X' 1579 expect 'xz' %b 'x\M-Yz' 1580 expect 'xz' %b 'x\M^wz' 1581 expect 'ab' %b 'a\^?b' 1582 expect '--' %b '-\M^?-' 1583 1584 expect 'A1b2c3D4' '\x411%b\x444' '\x622\x633' 1585 expect '"'\' %b\\\' '\"\e' 1586 expect '+' %b '\x1+\x3' 1587 expect '[1m' %b '\E[\61\x6d' 1588 1589 expect_fail "${BSL}" '\' 1590 expect_fail '@' '\@' 1591 expect_fail '%' '\%' 1592 expect_fail "${BSL}" %b '\' 1593 expect_fail '@' %b '\@' 1594 1595 # This is unspecified in posix: 1596 # If arg string uses no args, but there are some, run format just once 1597 expect 'hello world' 'hello world' a b c d 1598 1599 # Same as in format_escapes, but for \x (hex) constants 1600 atf_require_prog wc 1601 atf_require_prog od 1602 atf_require_prog tr 1603 1604 for fmt in '\x0' '\x00' 1605 do 1606 if [ $( do_printf "${fmt}" | wc -c ) -ne 1 ] 1607 then 1608 atf_fail \ 1609 "printf '${fmt}' did not output exactly 1 character (byte)" 1610 elif [ $(( $( do_printf "${fmt}" | od -A n -to1 ) )) -ne 0 ] 1611 then 1612 1613 RES="$( do_printf "${fmt}" | od -A n -to1 | tr -d ' ')" 1614 atf_fail \ 1615 "printf '${fmt}' output was '\\${RES}' should be '\\000'" 1616 fi 1617 done 1618 1619 # We get different results here from the builtin and command 1620 # versions of printf ... OK, as which result is unspecified. 1621 if $BUILTIN_TEST 1622 then 1623 if [ $( do_printf %c '' | wc -c ) -ne 0 ] 1624 then 1625 atf_require_prog sed 1626 1627 RES="$( do_printf %c '' | 1628 od -A n -to1 | 1629 sed -e 's/ [0-9]/\\&/g' -e 's/ //g' )" 1630 atf_fail \ 1631 "printf %c '' did not output nothing: got '${RES}'" 1632 fi 1633 else 1634 if [ $( do_printf %c '' | wc -c ) -ne 1 ] 1635 then 1636 atf_require_prog sed 1637 1638 RES="$( do_printf %c '' | 1639 od -A n -to1 | 1640 sed -e 's/ [0-9]/\\&/g' -e 's/ //g' )" 1641 atf_fail \ 1642 "printf %c '' did not output nothing: got '${RES}'" 1643 elif [ $(( $( do_printf %c '' | od -A n -to1 ) )) -ne 0 ] 1644 then 1645 RES="$( do_printf %c '' | od -A n -to1 | tr -d ' ')" 1646 atf_fail \ 1647 "printf %c '' output was '\\${RES}' should be '\\000'" 1648 fi 1649 fi 1650 1651 return $RVAL 1652 } 1653 define NetBSD_extensions "Local NetBSD additions to printf" 1654 1655 B_string_expand() 1656 { 1657 setmsg B_string_expand 1658 1659 if ! supported B 1660 then 1661 atf_skip "%B format not supported" 1662 return $RVAL 1663 fi 1664 1665 # Even if %B is supported, it is not necessarily *our* %B ... 1666 1667 if $BUILTIN_TEST 1668 then 1669 # what matters if $TEST_SH is a NetBSD sh 1670 ${TEST_SH} -c 'test -n "$NETBSD_SHELL"' || { 1671 atf_skip \ 1672 "- ${TEST_SH%% *} is not a (modern) NetBSD shell" 1673 return $RVAL 1674 } 1675 else 1676 atf_require_prog uname 1677 1678 SYS="$(uname -s)" 1679 case "${SYS}" in 1680 (NetBSD) ;; 1681 (*) atf_skip "- Not NetBSD (is $SYS), %B format unspecified" 1682 return $RVAL 1683 ;; 1684 esac 1685 fi 1686 1687 # The trivial stuff... 1688 expect abcd %B abcd 1689 expect ' abcd' %5B abcd 1690 expect 'abcd ' %-5B abcd 1691 expect ab %.2B abcd 1692 expect ' ab' %5.2B abcd 1693 expect 'ab ' %-5.2B abcd 1694 1695 # Next the semi-trivial 1696 expect "abcd${BSL}n" %B "abcd${NL}" 1697 expect "ab${BSL}tcd" %B "ab cd" 1698 expect "${BSL}\"${BSL}e${BSL}a${BSL}b${BSL}f${BSL}r${BSL}v" \ 1699 %B '" ' 1703 expect "${BSL}'${BSL}^?" %B \''' 1704 expect "${BSL}^A${BSL}^B" %B '' 1705 expect "x${BSL}M-Yz" %B 'xz' 1706 expect "-${BSL}M^W-" %B '--' 1707 expect ":${BSL}M^?:" %B '::' 1708 1709 # Then, more or less nonsense 1710 expect " abcd${BSL}n" %9B "abcd${NL}" 1711 expect "ab${BSL}tcd " %-9B "ab cd" 1712 expect " ${BSL}'${BSL}^?" %6B \''' 1713 expect "${BSL}^A${BSL}^B " %-7B '' 1714 expect " -${BSL}M^W-" %8B '--' 1715 expect ":${BSL}M^?: " %-8B '::' 1716 1717 # and finally, the absurd, ridiculous, and bizarre (useless) 1718 expect "abcd${BSL}" %.5B "abcd${NL}" 1719 expect "ab${BSL}" %.3B "ab cd" 1720 expect "${BSL}\"${BSL}" %.3B '" ' 1724 expect "${BSL}" %.1B \''' 1725 expect "${BSL}^" %.2B '' 1726 expect "x${BSL}M-" %.4B 'xz' 1727 expect "-${BSL}M^" %.4B '--' 1728 expect ":${BSL}M" %.3B '::' 1729 1730 return $RVAL 1731 } 1732 define B_string_expand "NetBSD specific %B string expansion" 1733 1734 1735 ############################################################################# 1736 ############################################################################# 1737 # 1738 # The code to make the tests above actually run starts here... 1739 # 1740 1741 # if setup fails, then ignore any test names on command line 1742 # Just run the (one) test that setup() established 1743 setup || set -- 1744 1745 NL=' 1746 ' 1747 # test how the shell we're running handles quoted patterns in vars 1748 # Note: it is not our task here to diagnose the broken shell 1749 B1='\' 1750 B2='\\' 1751 case "${B1}" in 1752 (${B2}) BSL="${B2}";; # This one is correct 1753 (${B1}) BSL="${B1}";; # but some shells can't handle that 1754 (*) BSL=BROKEN_SHELL;; # !!! 1755 esac 1756 1757 if $Running_under_ATF 1758 then 1759 # When in ATF, just add the test cases, and finish, and ATF 1760 # will take care of running everything 1761 1762 atf_init_test_cases() { 1763 1764 for T in $Tests 1765 do 1766 atf_add_test_case "$T" 1767 done 1768 return 0 1769 } 1770 exec 3>&2 1771 else 1772 # When not in AFT, we need to do it all here... 1773 1774 Failed= 1775 Failures=0 1776 1777 STDERR=$(mktemp ${TMPDIR:-/tmp}/Test-XXXXXX) 1778 trap "rm -f '${STDERR}'" EXIT 1779 exec 3>"${STDERR}" 1780 1781 case "$#" in 1782 (0) set -- $Tests ;; 1783 esac 1784 1785 for T 1786 do 1787 $T || { 1788 Failed="${Failed}${Failed:+${NL}} ${T} : " 1789 eval Failed='${Failed}${TEST_'"${T}"'_MSG}' 1790 Failures=$(( $Failures + 1 )) 1791 } 1792 done 1793 if [ $Failures -gt 0 ] 1794 then 1795 s=s 1796 test $Failures -eq 1 && s= 1797 1798 exec >&2 1799 echo 1800 echo ================================================= 1801 echo 1802 echo "$Failures test$s failed:" 1803 echo "$Failed" 1804 echo 1805 echo ================================================= 1806 1807 if test -s "${STDERR}" 1808 then 1809 echo 1810 echo The following appeared on stderr during the tests: 1811 echo 1812 cat "${STDERR}" 1813 fi 1814 fi 1815 fi 1816