printf.sh revision 1.1 1 # $NetBSD: printf.sh,v 1.1 2018/09/05 21:05:40 kre 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 for A in '' -- -@ # hope that '@' is not an option to printf...
210 do
211 if (do_printf $A >/dev/null 2>&1)
212 then
213 atf_fail "${A:-with no args} successful"
214 fi
215 if test -n "$( do_printf 2>/dev/null )"
216 then
217 atf_fail "${A:-with no args} produces text on stdout"
218 fi
219 if test -z "$( do_printf 2>&1 )"
220 then
221 atf_fail "${A:-with no args} no err/usage message"
222 fi
223
224 test -z "$A" && continue
225
226 if (do_printf "%${A}%" >/dev/null 2>&1)
227 then
228 atf_fail "%${A}% successful"
229 fi
230 done
231
232 expect abcd abcd
233 expect % %%
234 expect xxx%yyy xxx%%yyy
235 expect -123 -- -123
236
237 # technically these are all unspecified, but the only rational thing
238 expect_fail '' %3%
239 expect_fail '' -123
240 expect_fail a a%.%
241 expect_fail '' '%*%b' # cannot continue after bad format
242 expect_fail a a%-%b # hence 'b' is not part of output
243
244 return $RVAL
245 }
246 define basic 'basic functionality'
247
248 format_escapes()
249 {
250 setmsg format_escapes
251
252 expect "${BSL}" '\\'
253 expect '?' '\\' # must be just 1 char
254
255 expect "${NL}" '\n'
256 expect " " '\t' # a literal <tab> in " "
257
258 expect "0" '\60'
259 expect "1" '\061'
260 expect "21" '\0621'
261 expect "${NL}" '\12'
262 expect "" '\1'
263
264 expect "" '\b'
265 expect "" '\f'
267 expect "
" '\r'
269 expect "" '\a'
270 expect "" '\v'
272
273 expect "hello${NL}world${NL}!!${NL}" 'hello\nworld\n\a\a!!\n'
274
275 atf_require_prog wc
276 atf_require_prog od
277 atf_require_prog tr
278
279 for fmt in '\0' '\00' '\000'
280 do
281 RES=$(( $( do_printf "${fmt}" | wc -c ) ))
282 if [ "${RES}" -ne 1 ]
283 then
284 atf_fail "'${fmt}' output $RES bytes, expected 1"
285 elif [ $(( $( do_printf "${fmt}" | od -A n -to1 ) )) -ne 0 ]
286 then
287 RES="$( do_printf "${fmt}" | od -A n -to1 | tr -d ' ')"
288 atf_fail \
289 "'${fmt}' output was '\\${RES}' should be '\\000'"
290 fi
291 done
292
293 # There are no expected failures here, as all other \Z
294 # sequences produce unspecified results -- anything is OK.
295
296 return $RVAL
297 }
298 define format_escapes "backslash escapes in format string"
299
300 s_strings()
301 {
302 setmsg s_strings
303
304 # The # and 0 flags produce undefined results (so don't test)
305 # The + and ' ' flags are ignored (only apply to signed conversions)
306
307 expect abcd %s abcd
308 expect ' a' %3s a
309 expect 'a ' %-3s a
310 expect abcd %3s abcd
311 expect abcd %-3s abcd
312
313 expect a %.1s abcd
314 expect ab %.2s abcd
315 expect abc %.3s abcd
316 expect abcd %.4s abcd
317 expect abcd %.5s abcd
318 expect abcd %.6s abcd
319
320 expect ' a' %4.1s abcd
321 expect ' ab' %4.2s abcd
322 expect ' abc' %4.3s abcd
323 expect abcd %4.4s abcd
324 expect abcd %4.5s abcd
325 expect abcd %4.6s abcd
326
327 expect ' a' %7.1s abcd
328 expect 'ab ' %-7.2s abcd
329 expect ' abc' %7.3s abcd
330 expect ' abcd' %7.4s abcd
331 expect 'abcd ' %-7.5s abcd
332 expect ' abcd' %7.6s abcd
333
334 expect 'aba a' %.2s%.1s%2.1s abcd abcd abcd
335
336 expect 123 %s 123
337 expect 1 %.1s 123
338 expect 12 %+.2s 123
339 expect -1 %+.2s -123
340 expect 12 '% .2s' 123
341 expect -1 '%+.2s' -123
342
343 expect '' %s ''
344 expect ' ' %1s ''
345 expect ' ' %6s ''
346 expect ' ' %2.1s ''
347 expect '' %.0s abcd
348 expect ' ' %2.0s abcd
349 expect ' ' %-3.0s abcd
350
351 # %s is just so boring! There are no possible failures to test.
352
353 return $RVAL
354 }
355 define s_strings "%s string output"
356
357 c_chars()
358 {
359 setmsg c_chars
360
361 expect a '%c' a
362 expect a '%c' abc
363 expect 'ad' '%c%c' abc def
364 expect '@ a@a @' "@%3c@%-3c@" a a
365 expect '@ a@a @' "@%2c@%-4c@" a a
366
367 # do not test with '' (null string) as operand to %c
368 # as whether that produces \0 or nothing is unspecified.
369 # (test NetBSD specific behaviour in NetBSD specific test)
370
371 return $RVAL
372 }
373 define c_chars '%c (character) format conversions'
374
375 d_decimal()
376 {
377 setmsg d_decimal
378
379 expect 0 '%d' 0
380 expect 1 '%d' 1
381 expect 999 '%d' 999
382 expect -77 '%d' -77
383 expect 51 '%d' 0x33
384 expect 51 '%d' 063
385
386 expect ' 2' '%4d' 2
387 expect '0002' '%04d' 2
388 expect '-002' '%04d' -2
389 expect '2 ' '%-4d' 2
390 expect ' 02' '%4.2d' 2
391 expect ' 22' '%4.2d' 22
392 expect ' 222' '%4.2d' 222
393 expect '2222' '%4.2d' 2222
394 expect '22222' '%4.2d' 22222
395 expect ' -02' '%4.2d' -2
396 expect '02 ' '%-4.2d' 2
397 expect '-02 ' '%-4.2d' -2
398 expect '22 ' '%-4.2d' 22
399 expect '222 ' '%-4.2d' 222
400 expect '2222' '%-4.2d' 2222
401 expect '22222' '%-4.2d' 22222
402 expect 1 '%.0d' 1
403 expect '' '%.0d' 0
404 expect '' '%.d' 0
405 expect ' ' '%3.d' 0
406 expect ' ' '%-4.d' 0
407 expect ' ' '%05.d' 0
408
409 expect 65 '%d' "'A"
410 expect 065 '%03d' "'A"
411 expect 49 '%d' "'1"
412 expect 45 '%d' "'-1"
413 expect 43 '%d' "'+1"
414
415 expect 68 '%d' '"D'
416 expect 069 '%03d' '"E'
417 expect 51 '%d' '"3'
418 expect 45 '%d' '"-3'
419 expect 43 '%d' '"+3'
420
421 expect -1 '% d' -1
422 expect ' 1' '% d' 1
423 expect -1 '% 1d' -1
424 expect ' 1' '% 1d' 1
425 expect -1 '% 0d' -1
426 expect ' 1' '% 0d' 1
427 expect ' -1' '% 5d' -1
428 expect ' 1' '% 5d' 1
429 expect ' 01' '%0 3d' 1
430 expect '-01' '%0 3d' -1
431 expect ' 03' '% 4.2d' 3
432 expect ' -03' '% 4.2d' -3
433
434 expect -1 '%+d' -1
435 expect +1 '%+d' 1
436 expect ' -7' '%+3d' -7
437 expect ' +7' '%+3d' 7
438 expect ' -02' '%+4.2d' -2
439 expect ' +02' '%+4.2d' 2
440 expect '-09 ' '%-+4.2d' -9
441 expect '+09 ' '%+-4.2d' 9
442
443 # space flag is ignored if + is given, so same results as just above
444 expect -1 '%+ d' -1
445 expect +1 '%+ d' 1
446 expect ' -7' '%+ 3d' -7
447 expect ' +7' '%+ 3d' 7
448 expect ' -02' '%+ 4.2d' -2
449 expect ' +02' '%+ 4.2d' 2
450 expect '-09 ' '%- +4.2d' -9
451 expect '+09 ' '% +-4.2d' 9
452
453 expect_fail '0' %d junk
454 expect_fail '123' %d 123kb
455 expect_fail '15' %d 0xfooD
456
457 expect_fail '0 1 2' %d%2d%2d junk 1 2
458 expect_fail '3 1 2' %d%2d%2d 3 1+1 2
459
460 return $RVAL
461 }
462 define d_decimal '%d (decimal integer) conversions'
463
464 i_decimal()
465 {
466 setmsg i_decimal
467
468 supported i || {
469 atf_skip "%i conversion not supported"
470 return $RVAL
471 }
472
473 expect 0 '%i' 0
474 expect 1 '%i' 1
475 expect 999 '%i' 999
476 expect -77 '%i' -77
477 expect 51 '%i' 0x33
478 expect 51 '%i' 063
479 expect '02 ' '%-4.2i' 2
480 expect ' +02' '%+ 4.2i' 2
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 45 '%u' "'-1"
534 expect 43 '%u' "'+1"
535
536 expect 68 '%u' '"D'
537 expect 069 '%03u' '"E'
538 expect 51 '%u' '"3'
539 expect 45 '%u' '"-3'
540 expect 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 55 '%o' "'-1"
611 expect 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 055 '%#o' "'-1"
620 expect 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 2d '%x' "'-1"
659 expect 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 2D %X "'-1"
697 expect 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 6.500000e+01 '%e' "'A"
1003 expect 6.5e+01 '%.1e' "'A"
1004 expect 5e+01 '%.0e' "'1"
1005 expect 4.50e+01 '%.2e' "'-1"
1006 expect 4.300e+01 '%.3e' "'+1"
1007
1008 expect_fail 0.000000e+00 '%e' NOT-E
1009 expect_fail 1.200000e+00 '%e' 1.2Gb
1010
1011 return $RVAL
1012 }
1013 define e_floats "%e floating point conversions"
1014
1015 E_floats()
1016 {
1017 setmsg E_floats
1018
1019 supported E || {
1020 atf_skip "%E conversion not supported"
1021 return $RVAL
1022 }
1023
1024 # don't bother duplicating all the above, the only differences
1025 # should be 'E' instead of 'e', and INF/NAN (for inf/nan)
1026 # so just pick a few...
1027
1028 expect 0.000000E+00 %E 0
1029 expect -4.300000E+01 %E -43
1030 expect 1E+00 %.0E 1
1031 expect 1.E+00 %#.0E 1
1032 expect '-9.00E+00 ' %-010.2E -9
1033 expect2 INF INFINITY %E InFinity
1034 expect2 NAN 'NAN(*)' %E NaN
1035
1036 return $RVAL
1037 }
1038 define E_floats "%E floating point conversions"
1039
1040
1041 g_floats()
1042 {
1043 setmsg g_floats
1044
1045 supported g || {
1046 atf_skip "%g conversion not supported"
1047 return $RVAL
1048 }
1049
1050 # for a value writtem in %e format, which has an exponent of x
1051 # then %.Pg will produce 'f' format if x >= -4, and P > x,
1052 # otherwise it produces 'e' format.
1053 # When 'f' is used, the precision associated is P-x-1
1054 # when 'e' is used, the precision is P-1
1055
1056 # then trailing 0's are deleted (unless # flag is present)
1057
1058 # since we have other tests for 'f' and 'e' formats, rather
1059 # than testing lots of random numbers, instead test that the
1060 # switchover between 'f' and 'e' works properly.
1061
1062 expect 1 %.1g 1 # p = 1, x = 0 : %.0f
1063 expect 0.5 %.1g 0.5 # p = 1, x = -1: %.1f
1064 expect 1 %.2g 1 # p = 2, x = 0 : %.1f
1065 expect 0.5 %.2g 0.5 # p = 2, x = -1: %.2f
1066
1067 expect 1 %g 1 # p = 6, x = 0 : %.5f
1068 expect -0.5 %g -0.5 # p = 6, x = -1: %.6f
1069
1070 expect 0.001234 %.4g 0.001234 # p= 4, x = -3: %.6f
1071
1072 expect 9999 %.4g 9999 # p = 4, x = 3 : %.0f
1073 expect 9999 %.5g 9999 # p = 5, x = 3 : %.1f
1074
1075 expect 1. %#.1g 1 # p = 1, x = 0 : %.0f
1076 expect 0.5 %#.1g 0.5 # p = 1, x = -1: %.1f
1077 expect 1.0 %#.2g 1 # p = 2, x = 0 : %.1f
1078 expect 0.50 %#.2g 0.5 # p = 2, x = -1: %.2f
1079
1080 expect 1.00000 %#g 1 # p = 6, x = 0 : %.5f
1081 expect -0.500000 %#g -0.5 # p = 6, x = -1: %.6f
1082
1083 expect 0.001234 %#.4g 0.001234 # p= 4, x = -3: %.6f
1084
1085 expect 9999. %#.4g 9999 # p = 4, x = 3 : %.0f
1086 expect 9999.0 %#.5g 9999 # p = 5, x = 3 : %.1f
1087
1088 expect 4.4?e+03 %.3g 4444 # p = 3, x = 3 : %.2e
1089 expect 1.2e-05 %.2g 0.000012 # p = 2, x = -5: $.1e
1090
1091 expect2 inf infinity %g Infinity
1092 expect2 -inf -infinity %g -INF
1093 expect2 nan 'nan(*)' %g NaN
1094
1095 return $RVAL
1096 }
1097 define g_floats '%g (floating) conversions'
1098
1099 G_floats()
1100 {
1101 setmsg G_floats
1102
1103 supported G || {
1104 atf_skip "%G conversion not supported"
1105 return $RVAL
1106 }
1107
1108 # 'G' uses 'F' or 'E' instead or 'f' or 'e'.
1109
1110 # F is different from f only for INF/inf NAN/nan which there is
1111 # no point testing here (those simply use F/f format, tested there.
1112 # E is different for those, and also uses 'E' for the exponent
1113 # That is the only thing to test, so ...
1114
1115 expect 1.2E-05 %.2G 0.000012 # p = 2, x = -5: $.1e
1116
1117 expect2 INF INFINITY %G Infinity
1118 expect2 -INF -INFINITY %G -INF
1119 expect2 NAN 'NAN(*)' %G NaN
1120
1121 return $RVAL
1122 }
1123 define G_floats '%G (floating) conversions'
1124
1125 # It is difficul;t to test correct results from the %a conversions,
1126 # as they depend upon the underlying floating point format (not
1127 # necessarily IEEE) and other factors chosen by the implementation,
1128 # eg: the (floating) number 1 could be 0x8p-3 0x4p-2 0x1p-1 even
1129 # assuming IEEE formats wnen using %.0a. But we can test 0
1130 a_floats()
1131 {
1132 setmsg a_floats
1133
1134 supported a || {
1135 atf_skip "%a conversion not supported"
1136 return $RVAL
1137 }
1138
1139 expect 0x0p+0 '%.0a' 0
1140 expect 0x0.p+0 '%#.0a' 0
1141 expect 0x0.000p+0 '%.3a' 0
1142 expect '0x?.*p+*' '%a' 123
1143 expect '0x?.*p-*' '%a' 0.123
1144
1145 # We can check that the %a result can be used as input to %f
1146 # and obtain the original value (nb: input must be in %.4f format)
1147
1148 for VAL in 1.0000 2.0000 3.0000 4.0000 0.5000 0.1000 1000.0000 \
1149 777777.0000 0.1234 -1.0000 -0.2500 -123.4567
1150 do
1151 A_STRING=$( do_printf '%a' "${VAL}" 2>&3 )
1152
1153 expect "${VAL}" "%.4f" "${A_STRING}"
1154 done
1155
1156 expect_fail 0x0p+0 %a trash
1157 expect_fail 0x0.p+0 %#a trash
1158 expect_fail X0x0p+0Y X%aY trash
1159 expect_fail 0x0p+00x0p+0 %a%a trash garbage
1160
1161 return $RVAL
1162 }
1163 define a_floats '%a floating conversion'
1164
1165 A_floats()
1166 {
1167 setmsg A_floats
1168
1169 supported A || {
1170 atf_skip "%A conversion not supported"
1171 return $RVAL
1172 }
1173
1174 expect 0X0P+0 '%.0A' 0
1175 expect 0X0.P+0 '%#.0A' 0
1176 expect 0X0.000P+0 '%.3A' 0
1177 expect '0X?.*P+*' '%A' 123
1178 expect '0X?.*P-*' '%A' 0.123
1179
1180 for VAL in 1.0000 2.0000 3.0000 4.0000 0.5000 0.1000 1000.0000 \
1181 777777.0000 0.1234 -1.0000 -0.2500 -123.4567
1182 do
1183 A_STRING=$( do_printf '%A' "${VAL}" 2>&3 )
1184
1185 expect "${VAL}" "%.4f" "${A_STRING}"
1186 done
1187
1188 expect_fail 0X0P+0 %A trash
1189 expect_fail 0X0.P+0 %#A trash
1190 expect_fail X0X0P+0X X%AX trash
1191 expect_fail 0X0P+00X0P+0 %A%A trash garbage
1192
1193 return $RVAL
1194 }
1195 define A_floats '%A floating conversion'
1196
1197 missing_args()
1198 {
1199 setmsg missing_args
1200
1201 # Note: missing string arg is replaced by "" and behaviour
1202 # of %c is either nothing or '\0' in that case, so avoid
1203 # testing missing arg for %c.
1204
1205
1206 expect '' %s
1207 expect '' %b
1208 expect 0 %d
1209 expect 0 %o
1210 expect 0 %x
1211 expect 0 %#o
1212 expect 0 %#X
1213
1214 expect 'xxxyyyzzz' '%syyy%szzz' xxx
1215 expect 'a=1, b=0' 'a=%d, b=%d' 1
1216
1217 expect 000000 %d%u%i%x%o%X
1218 expect 437000 %d%u%i%x%o%X 4 3 7
1219
1220 if supported f
1221 then
1222 expect 0.000000 %f
1223 expect 'x=0.0' '%s=%.1f' x
1224 fi
1225
1226 return $RVAL
1227 }
1228 define missing_args "format string when there are no more args"
1229
1230 repeated_format()
1231 {
1232 setmsg repeated_format
1233
1234 expect abcd %s a b c d
1235 expect 1234 %d 1 2 3 4
1236 expect ' 1 2 3 4' %2d 1 2 3 4
1237 expect abcd %.1s aaa bbb ccc ddd
1238 expect ' a=1 b=2 c=3' %2s=%d a 1 b 2 c 3
1239 expect "hello${NL}world${NL}" '%s\n' hello world
1240 expect "a${NL}b${NL}c${NL}d${NL}" '%.1s\n' aaa bbb ccc ddd
1241
1242 expect "\
1243 1.00"'
1244 9.75
1245 -3.00
1246 999.99
1247 -101.01'"${NL}" '%7.2f\n' 1 9.75 -3 999.99 -101.01
1248
1249 expect " 1 010x1${NL} 220260x16${NL} 9201340x5c${NL}" \
1250 '%3d%#3o%#3x\n' 1 1 1 22 22 22 92 92 92
1251
1252 expect ' 1 2 3 4 5' %2d 1 2 3 4 5
1253 expect ' 1 2 3 4 5 0' %2d%2d%2d 1 2 3 4 5
1254
1255
1256 return $RVAL
1257 }
1258 define repeated_format 'format string is reused until all args used'
1259
1260 b_SysV_echo()
1261 {
1262 setmsg b_SysV_echo
1263
1264 # Basic formatting
1265
1266 expect '' %b ''
1267 expect '' %.0b abcd
1268 expect abcd %b abcd
1269 expect ' ab' %3.2b abcd
1270 expect 'a ' %-3.1b abcd
1271 expect ' ' %3.0b abcd
1272
1273 # The simple stuff. nb: no \c tests, it has a whole test case to itself
1274
1275 expect "${BSL} ${NL}" %b '\\\t\n'
1276 expect '
' %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
" %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 }
1337 define b_SysV_echo '%b format - emulate SysV echo escapes'
1338
1339 b_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 return $RVAL
1356 }
1357 define b_SysV_echo_backslash_c 'Use of \c in arg to %b format'
1358
1359 indirect_width()
1360 {
1361 setmsg indirect_width
1362
1363 supported '*d' 5 123 || {
1364 atf_skip "%*d not supported (indirect field width)"
1365 return $RVAL
1366 }
1367
1368 lpad= rpad= zpad=
1369 for i in 1 2 3 4 5 6 7 8 9 10
1370 do
1371 expect "${lpad}7" '%*d' "$i" 7
1372 expect "6${rpad}" '%-*d' "$i" 6
1373 expect "${zpad}5" '%0*d' "$i" 5
1374
1375 lpad="${lpad} "
1376 rpad="${rpad} "
1377 zpad="${zpad}0"
1378 done
1379
1380 return $RVAL
1381 }
1382 define indirect_width "using * to get field width from arg"
1383
1384 indirect_precision()
1385 {
1386 setmsg indirect_precision
1387
1388 supported '.*d' 5 123 || {
1389 atf_skip "%.*d not supported (indirect precision)"
1390 return $RVAL
1391 }
1392
1393 res= zpad=.
1394 for i in 0 1 2 3 4 5 6 7 8 9
1395 do
1396 expect "${res}" '%.*s' "$i" aaaaaaaaaaaaaaaa
1397 res="${res}a"
1398
1399 expect "3${zpad}" '%#.*f' "$i" 3
1400 zpad="${zpad}0"
1401 done
1402
1403 return $RVAL
1404 }
1405 define indirect_precision 'Using .* as to get precision from arg'
1406
1407 indirect_both()
1408 {
1409 setmsg indirect_both
1410
1411 supported '*.*d' 5 2 123 || {
1412 atf_skip "%*.*d not supported (indirect width & precision)"
1413 return $RVAL
1414 }
1415
1416 res=
1417 for i in 1 2 3 4 5 6 7 8
1418 do
1419 res="${res}z"
1420 expect " ${res}" '%*.*s' $(( $i + 2 )) "$i" zzzzzzzzzzz
1421 done
1422
1423 expect ' ab: 9: 1.20' "%*.*s:%*d:%*.*f" 4 2 abcde 3 9 5 2 1.2
1424
1425 return $RVAL
1426 }
1427 define indirect_both 'Using *.* as to get width & precision from args'
1428
1429 q_quoting()
1430 {
1431 setmsg q_quoting
1432
1433 if ! supported q
1434 then
1435 atf_skip '%q format not supported'
1436 return $RVAL
1437 fi
1438
1439 # Testing quoting isn't as straightforward as many of the
1440 # others, as there is no specific form in which the output
1441 # is required to appear
1442
1443 # Instead, we will apply %q to various strings, and then
1444 # process them again in this shell, and see if the string
1445 # we get back is the same as the string we started with.
1446
1447 for string in \
1448 abcd \
1449 'hello world' \
1450 '# a comment ....' \
1451 '' \
1452 'a* b* c*' \
1453 'ls | wc' \
1454 '[<> # | { ~.** } $@]' \
1455 '( who & echo $! )'
1456 do
1457 QUOTED="$(do_printf %q "$string")"
1458
1459 eval "RES=${QUOTED}"
1460
1461 if [ "${RES}" != "${string}" ]
1462 then
1463 atf_fail \
1464 "%q <<${string}>> as <<${QUOTED}>> makes <<${RES}>>"
1465 continue
1466 fi
1467
1468 QUOTED="$(do_printf %-32q "$string")"
1469
1470 if [ ${#QUOTED} -lt 32 ]
1471 then
1472 atf-fail \
1473 "%-32q <<${string}>> short result (${#QUOTED}) <<${QUOTED}>>"
1474
1475 fi
1476
1477 eval "RES=${QUOTED}"
1478 if [ "${RES}" != "${string}" ]
1479 then
1480 atf_fail \
1481 "%-32q <<${string}>> as <<${QUOTED}>> makes <<${RES}>>"
1482 continue
1483 fi
1484 done
1485
1486 # %q is a variant of %s, but using field width (except as above),
1487 # and especially precision makes no sense, and is implrmented so
1488 # badly that testing it would be hopeless. Other flags do nothing.
1489
1490 return $RVAL
1491 }
1492 define q_quoting '%q quote string suitably for sh processing'
1493
1494 NetBSD_extensions()
1495 {
1496 setmsg NetBSD_extensions
1497
1498 if $BUILTIN_TEST
1499 then
1500 # what matters if $TEST_SH is a NetBSD sh
1501 ${TEST_SH} -c 'test -n "$NETBSD_SHELL"' || {
1502 atf_skip \
1503 "- ${TEST_SH%% *} is not a (modern) NetBSD shell"
1504 return $RVAL
1505 }
1506 fi
1507 if ! supported '*.*%%_._' 78 66
1508 then
1509 if $BUILTIN_TEST
1510 then
1511 atf_skip \
1512 "- ${TEST_SH%% *} is not a (modern enough) NetBSD shell"
1513 else
1514 atf_skip "- ${PRINTF} is not a (modern) NetBSD printf"
1515 fi
1516 return $RVAL
1517 fi
1518
1519 # Even in the most modern NetBSD printf the data length modifiers
1520 # might not be supported.
1521
1522 if supported zd
1523 then
1524 expect 88888 %jd 88888
1525 expect 88888 %ld 88888
1526 expect 88888 %lld 88888
1527 expect 88888 %Ld 88888
1528 expect 88888 %td 88888
1529 expect 88888 %zd 88888
1530
1531 expect 23352 %hd 88888
1532 expect 56 %hhd 88888
1533
1534 expect 300000 %jd 300000
1535 expect 300000 %Ld 300000
1536 expect -27680 %hd 300000
1537 expect -32 %hhd 300000
1538
1539 expect 15b38 %jx 88888
1540 expect 5b38 %hx 88888
1541 expect 38 %hhx 88888
1542
1543 expect 93e0 %hx 300000
1544 expect e0 %hhx 300000
1545
1546 # to test modifiers attached to floats we'd need to
1547 # verify float support, so don't bother...
1548 fi
1549
1550 # NetBSD (non-POSIX) format excape extensions
1551 expect '' '\e'
1552 expect '' '\E'
1553 expect '' '\e\E'
1554
1555 # NetBSD (non-POSIX) %b string escape extensions
1556 expect '' %b '\^A\^a\1'
1557 expect 'S4=X' %b '\1234\75X'
1558 expect 'xz' %b 'x\M-Yz'
1559 expect 'xz' %b 'x\M^wz'
1560 expect 'ab' %b 'a\^?b'
1561 expect '--' %b '-\M^?-'
1562
1563 expect 'A1b2c3D4' '\x411%b\x444' '\x622\x633'
1564 expect '"'\' %b\\\' '\"\e'
1565 expect '+' %b '\x1+\x3'
1566 expect '[1m' %b '\E[\61\x6d'
1567
1568 expect_fail "${BSL}" '\'
1569 expect_fail '@' '\@'
1570 expect_fail '%' '\%'
1571 expect_fail "${BSL}" %b '\'
1572 expect_fail '@' %b '\@'
1573
1574 # This is unspecified in posix:
1575 # If arg string uses no args, but there are some, run format just once
1576 expect 'hello world' 'hello world' a b c d
1577
1578 # Same as in format_escapes, but for \x (hex) constants
1579 atf_require_prog wc
1580 atf_require_prog od
1581 atf_require_prog tr
1582
1583 for fmt in '\x0' '\x00'
1584 do
1585 if [ $( do_printf "${fmt}" | wc -c ) -ne 1 ]
1586 then
1587 atf_fail \
1588 "printf '${fmt}' did not output exactly 1 character (byte)"
1589 elif [ $(( $( do_printf "${fmt}" | od -A n -to1 ) )) -ne 0 ]
1590 then
1591
1592 RES="$( do_printf "${fmt}" | od -A n -to1 | tr -d ' ')"
1593 atf_fail \
1594 "printf '${fmt}' output was '\\${RES}' should be '\\000'"
1595 fi
1596 done
1597
1598 # We get different results here from the builtin and command
1599 # versions of printf ... OK, as which result is unspecified.
1600 if $BUILTIN_TEST
1601 then
1602 if [ $( do_printf %c '' | wc -c ) -ne 0 ]
1603 then
1604 atf_require_prog sed
1605
1606 RES="$( do_printf %c '' |
1607 od -A n -to1 |
1608 sed -e 's/ [0-9]/\\&/g' -e 's/ //g' )"
1609 atf_fail \
1610 "printf %c '' did not output nothing: got '${RES}'"
1611 fi
1612 else
1613 if [ $( do_printf %c '' | wc -c ) -ne 1 ]
1614 then
1615 atf_require_prog sed
1616
1617 RES="$( do_printf %c '' |
1618 od -A n -to1 |
1619 sed -e 's/ [0-9]/\\&/g' -e 's/ //g' )"
1620 atf_fail \
1621 "printf %c '' did not output nothing: got '${RES}'"
1622 elif [ $(( $( do_printf %c '' | od -A n -to1 ) )) -ne 0 ]
1623 then
1624 RES="$( do_printf %c '' | od -A n -to1 | tr -d ' ')"
1625 atf_fail \
1626 "printf %c '' output was '\\${RES}' should be '\\000'"
1627 fi
1628 fi
1629
1630 return $RVAL
1631 }
1632 define NetBSD_extensions "Local NetBSD additions to printf"
1633
1634 B_string_expand()
1635 {
1636 setmsg B_string_expand
1637
1638 if ! supported B
1639 then
1640 atf_skip "%B format not supported"
1641 return $RVAL
1642 fi
1643
1644 # Even if %B is supported, it is not necessarily *our* %B ...
1645
1646 if $BUILTIN_TEST
1647 then
1648 # what matters if $TEST_SH is a NetBSD sh
1649 ${TEST_SH} -c 'test -n "$NETBSD_SHELL"' || {
1650 atf_skip \
1651 "- ${TEST_SH%% *} is not a (modern) NetBSD shell"
1652 return $RVAL
1653 }
1654 else
1655 atf_require_prog uname
1656
1657 SYS="$(uname -s)"
1658 case "${SYS}" in
1659 (NetBSD) ;;
1660 (*) atf_skip "- Not NetBSD (is $SYS), %B format unspecified"
1661 return $RVAL
1662 ;;
1663 esac
1664 fi
1665
1666 # The trivial stuff...
1667 expect abcd %B abcd
1668 expect ' abcd' %5B abcd
1669 expect 'abcd ' %-5B abcd
1670 expect ab %.2B abcd
1671 expect ' ab' %5.2B abcd
1672 expect 'ab ' %-5.2B abcd
1673
1674 # Next the semi-trivial
1675 expect "abcd${BSL}n" %B "abcd${NL}"
1676 expect "ab${BSL}tcd" %B "ab cd"
1677 expect "${BSL}\"${BSL}e${BSL}a${BSL}b${BSL}f${BSL}r${BSL}v" \
1678 %B '"
'
1682 expect "${BSL}'${BSL}^?" %B \'''
1683 expect "${BSL}^A${BSL}^B" %B ''
1684 expect "x${BSL}M-Yz" %B 'xz'
1685 expect "-${BSL}M^W-" %B '--'
1686 expect ":${BSL}M^?:" %B '::'
1687
1688 # Then, more or less nonsense
1689 expect " abcd${BSL}n" %9B "abcd${NL}"
1690 expect "ab${BSL}tcd " %-9B "ab cd"
1691 expect " ${BSL}'${BSL}^?" %6B \'''
1692 expect "${BSL}^A${BSL}^B " %-7B ''
1693 expect " -${BSL}M^W-" %8B '--'
1694 expect ":${BSL}M^?: " %-8B '::'
1695
1696 # and finally, the absurd, ridiculous, and bizarre (useless)
1697 expect "abcd${BSL}" %.5B "abcd${NL}"
1698 expect "ab${BSL}" %.3B "ab cd"
1699 expect "${BSL}\"${BSL}" %.3B '"
'
1703 expect "${BSL}" %.1B \'''
1704 expect "${BSL}^" %.2B ''
1705 expect "x${BSL}M-" %.4B 'xz'
1706 expect "-${BSL}M^" %.4B '--'
1707 expect ":${BSL}M" %.3B '::'
1708
1709 return $RVAL
1710 }
1711 define B_string_expand "NetBSD specific %B string expansion"
1712
1713
1714 #############################################################################
1715 #############################################################################
1716 #
1717 # The code to make the tests above actually run starts here...
1718 #
1719
1720 # if setup fails, then ignore any test names on command line
1721 # Just run the (one) test that setup() established
1722 setup || set --
1723
1724 NL='
1725 '
1726 # test how the shell we're running handles quoted patterns in vars
1727 # Note: it is not our task here to diagnose the broken shell
1728 B1='\'
1729 B2='\\'
1730 case "${B1}" in
1731 (${B2}) BSL="${B2}";; # This one is correct
1732 (${B1}) BSL="${B1}";; # but some shells can't handle that
1733 (*) BSL=BROKEN_SHELL;; # !!!
1734 esac
1735
1736 if $Running_under_ATF
1737 then
1738 # When in ATF, just add the test cases, and finish, and ATF
1739 # will take care of running everything
1740
1741 atf_init_test_cases() {
1742
1743 for T in $Tests
1744 do
1745 atf_add_test_case "$T"
1746 done
1747 return 0
1748 }
1749 exec 3>&2
1750 else
1751 # When not in AFT, we need to do it all here...
1752
1753 Failed=
1754 Failures=0
1755
1756 STDERR=$(mktemp ${TMPDIR:-/tmp}/Test-XXXXXX)
1757 trap 'rm -f "${STDERR}"' EXIT
1758 exec 3>"${STDERR}"
1759
1760 case "$#" in
1761 (0) set -- $Tests ;;
1762 esac
1763
1764 for T
1765 do
1766 $T || {
1767 Failed="${Failed}${Failed:+${NL}} ${T} : "
1768 eval Failed='${Failed}${TEST_'"${T}"'_MSG}'
1769 Failures=$(( $Failures + 1 ))
1770 }
1771 done
1772 if [ $Failures -gt 0 ]
1773 then
1774 s=s
1775 test $Failures -eq 1 && s=
1776
1777 exec >&2
1778 echo
1779 echo =================================================
1780 echo
1781 echo "$Failures test$s failed:"
1782 echo "$Failed"
1783 echo
1784 echo =================================================
1785
1786 if test -s "${STDERR}"
1787 then
1788 echo
1789 echo The following appeared on stderr during the tests:
1790 echo
1791 cat "${STDERR}"
1792 fi
1793 fi
1794 fi
1795