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