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