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