OILS / spec / builtin-printf.test.sh View on Github | oilshell.org

1207 lines, 625 significant
1## oils_failures_allowed: 0
2## compare_shells: dash bash mksh zsh ash
3
4# printf
5# bash-completion uses this odd printf -v construction. It seems to mostly use
6# %s and %q though.
7#
8# %s should just be
9# declare $var='val'
10#
11# NOTE:
12# /usr/bin/printf %q "'" seems wrong.
13# $ /usr/bin/printf %q "'"
14# ''\'''
15#
16# I suppose it is technically correct, but it looks very ugly.
17
18#### printf with no args
19printf
20## status: 2
21## OK mksh/zsh status: 1
22## stdout-json: ""
23
24#### printf -v %s
25var=foo
26printf -v $var %s 'hello there'
27argv.py "$foo"
28## STDOUT:
29['hello there']
30## END
31## N-I mksh/zsh/ash STDOUT:
32-v['']
33## END
34## N-I dash STDOUT:
35['']
36## END
37
38#### printf -v %q
39val='"quoted" with spaces and \'
40
41# quote 'val' and store it in foo
42printf -v foo %q "$val"
43# then round trip back to eval
44eval "bar=$foo"
45
46# debugging:
47#echo foo="$foo"
48#echo bar="$bar"
49#echo val="$val"
50
51test "$bar" = "$val" && echo OK
52## STDOUT:
53OK
54## END
55## N-I mksh/zsh/ash stdout-json: "-v"
56## N-I mksh/zsh/ash status: 1
57## N-I dash stdout-json: ""
58## N-I dash status: 1
59
60#### printf -v a[1]
61a=(a b c)
62printf -v 'a[1]' %s 'foo'
63echo status=$?
64argv.py "${a[@]}"
65## STDOUT:
66status=0
67['a', 'foo', 'c']
68## END
69## N-I mksh/zsh STDOUT:
70-vstatus=0
71['a', 'b', 'c']
72## END
73## N-I dash/ash stdout-json: ""
74## N-I dash/ash status: 2
75
76#### printf -v syntax error
77printf -v 'a[' %s 'foo'
78echo status=$?
79## STDOUT:
80status=2
81## END
82## N-I ash/mksh/zsh stdout: -vstatus=0
83
84#### dynamic declare instead of %s
85var=foo
86declare $var='hello there'
87argv.py "$foo"
88## STDOUT:
89['hello there']
90## END
91## N-I dash/mksh/ash STDOUT:
92['']
93## END
94
95#### dynamic declare instead of %q
96var=foo
97val='"quoted" with spaces and \'
98# I think this is bash 4.4 only.
99declare $var="${val@Q}"
100echo "$foo"
101## STDOUT:
102'"quoted" with spaces and \'
103## END
104## OK osh STDOUT:
105$'"quoted" with spaces and \\'
106## END
107## N-I dash/ash stdout-json: ""
108## N-I dash/ash status: 2
109## N-I mksh stdout-json: "\n"
110## N-I zsh stdout-json: ""
111## N-I zsh status: 1
112
113#### printf -v dynamic scope
114case $SH in mksh|zsh|dash|ash) echo not implemented; exit ;; esac
115# OK so printf is like assigning to a var.
116# printf -v foo %q "$bar" is like
117# foo=${bar@Q}
118dollar='dollar'
119f() {
120 local mylocal=foo
121 printf -v dollar %q '$' # assign foo to a quoted dollar
122 printf -v mylocal %q 'mylocal'
123 echo dollar=$dollar
124 echo mylocal=$mylocal
125}
126echo dollar=$dollar
127echo --
128f
129echo --
130echo dollar=$dollar
131echo mylocal=$mylocal
132## STDOUT:
133dollar=dollar
134--
135dollar=\$
136mylocal=mylocal
137--
138dollar=\$
139mylocal=
140## END
141## OK osh STDOUT:
142dollar=dollar
143--
144dollar='$'
145mylocal=mylocal
146--
147dollar='$'
148mylocal=
149## END
150## N-I dash/ash/mksh/zsh STDOUT:
151not implemented
152## END
153
154#### printf with too few arguments
155printf -- '-%s-%s-%s-\n' 'a b' 'x y'
156## STDOUT:
157-a b-x y--
158## END
159
160#### printf with too many arguments
161printf -- '-%s-%s-\n' a b c d e
162## STDOUT:
163-a-b-
164-c-d-
165-e--
166## END
167
168#### printf width strings
169printf '[%5s]\n' abc
170printf '[%-5s]\n' abc
171## STDOUT:
172[ abc]
173[abc ]
174## END
175
176#### printf integer
177printf '%d\n' 42
178printf '%i\n' 42 # synonym
179printf '%d\n' \'a # if first character is a quote, use character code
180printf '%d\n' \"a # double quotes work too
181printf '[%5d]\n' 42
182printf '[%-5d]\n' 42
183printf '[%05d]\n' 42
184#printf '[%-05d]\n' 42 # the leading 0 is meaningless
185#[42 ]
186## STDOUT:
18742
18842
18997
19097
191[ 42]
192[42 ]
193[00042]
194## END
195
196#### printf %6.4d -- "precision" does padding for integers
197printf '[%6.4d]\n' 42
198printf '[%.4d]\n' 42
199printf '[%6.d]\n' 42
200echo --
201printf '[%6.4d]\n' -42
202printf '[%.4d]\n' -42
203printf '[%6.d]\n' -42
204## STDOUT:
205[ 0042]
206[0042]
207[ 42]
208--
209[ -0042]
210[-0042]
211[ -42]
212## END
213
214#### printf %6.4x X o
215printf '[%6.4x]\n' 42
216printf '[%.4x]\n' 42
217printf '[%6.x]\n' 42
218echo --
219printf '[%6.4X]\n' 42
220printf '[%.4X]\n' 42
221printf '[%6.X]\n' 42
222echo --
223printf '[%6.4o]\n' 42
224printf '[%.4o]\n' 42
225printf '[%6.o]\n' 42
226## STDOUT:
227[ 002a]
228[002a]
229[ 2a]
230--
231[ 002A]
232[002A]
233[ 2A]
234--
235[ 0052]
236[0052]
237[ 52]
238## END
239
240#### %06d zero padding vs. %6.6d
241printf '[%06d]\n' 42
242printf '[%06d]\n' -42 # 6 TOTAL
243echo --
244printf '[%6.6d]\n' 42
245printf '[%6.6d]\n' -42 # 6 + 1 for the - sign!!!
246## STDOUT:
247[000042]
248[-00042]
249--
250[000042]
251[-000042]
252## END
253
254#### %06x %06X %06o
255printf '[%06x]\n' 42
256printf '[%06X]\n' 42
257printf '[%06o]\n' 42
258## STDOUT:
259[00002a]
260[00002A]
261[000052]
262## END
263
264#### %06s is no-op
265printf '(%6s)\n' 42
266printf '(%6s)\n' -42
267printf '(%06s)\n' 42
268printf '(%06s)\n' -42
269echo status=$?
270## STDOUT:
271( 42)
272( -42)
273( 42)
274( -42)
275status=0
276## END
277# mksh is stricter
278## OK mksh STDOUT:
279( 42)
280( -42)
281((status=1
282## END
283
284#### printf %6.4s does both truncation and padding
285printf '[%6s]\n' foo
286printf '[%6.4s]\n' foo
287printf '[%-6.4s]\n' foo
288printf '[%6s]\n' spam-eggs
289printf '[%6.4s]\n' spam-eggs
290printf '[%-6.4s]\n' spam-eggs
291## STDOUT:
292[ foo]
293[ foo]
294[foo ]
295[spam-eggs]
296[ spam]
297[spam ]
298## END
299
300#### printf %6.0s and %0.0s
301printf '[%6.0s]\n' foo
302printf '[%0.0s]\n' foo
303## STDOUT:
304[ ]
305[]
306## END
307## N-I mksh stdout-json: "[ ]\n["
308## N-I mksh status: 1
309
310#### printf %6.s and %0.s
311printf '[%6.s]\n' foo
312printf '[%0.s]\n' foo
313## STDOUT:
314[ ]
315[]
316## END
317## BUG zsh STDOUT:
318[ foo]
319[foo]
320## END
321## N-I mksh stdout-json: "[ ]\n["
322## N-I mksh status: 1
323
324#### printf %*.*s (width/precision from args)
325printf '[%*s]\n' 9 hello
326printf '[%.*s]\n' 3 hello
327printf '[%*.3s]\n' 9 hello
328printf '[%9.*s]\n' 3 hello
329printf '[%*.*s]\n' 9 3 hello
330## STDOUT:
331[ hello]
332[hel]
333[ hel]
334[ hel]
335[ hel]
336## END
337
338#### unsigned / octal / hex
339printf '[%u]\n' 42
340printf '[%o]\n' 42
341printf '[%x]\n' 42
342printf '[%X]\n' 42
343echo
344
345printf '[%X]\n' \'a # if first character is a quote, use character code
346printf '[%X]\n' \'ab # extra chars ignored
347
348## STDOUT:
349[42]
350[52]
351[2a]
352[2A]
353
354[61]
355[61]
356## END
357
358#### unsigned / octal / hex big
359
360for big in $(( 1 << 32 )) $(( (1 << 63) - 1 )); do
361 printf '[%u]\n' $big
362 printf '[%o]\n' $big
363 printf '[%x]\n' $big
364 printf '[%X]\n' $big
365 echo
366done
367
368## STDOUT:
369[4294967296]
370[40000000000]
371[100000000]
372[100000000]
373
374[9223372036854775807]
375[777777777777777777777]
376[7fffffffffffffff]
377[7FFFFFFFFFFFFFFF]
378
379## END
380
381## BUG mksh STDOUT:
382[1]
383[1]
384[1]
385[1]
386
387[2147483647]
388[17777777777]
389[7fffffff]
390[7FFFFFFF]
391
392## END
393
394#### empty string (osh is more strict)
395printf '%d\n' ''
396## OK osh stdout-json: ""
397## OK osh status: 1
398## OK ash status: 1
399## STDOUT:
4000
401## END
402
403#### No char after ' => zero code point
404
405# most shells use 0 here
406printf '%d\n' \'
407printf '%d\n' \"
408
409## OK mksh status: 1
410## STDOUT:
4110
4120
413## END
414
415#### Unicode char with '
416case $SH in mksh) echo 'weird bug'; exit ;; esac
417
418# the mu character is U+03BC
419
420printf '%x\n' \'μ
421printf '%u\n' \'μ
422printf '%o\n' \'μ
423echo
424
425u3=三
426# u4=😘
427
428printf '%x\n' \'$u3
429printf '%u\n' \'$u3
430printf '%o\n' \'$u3
431echo
432
433# mksh DOES respect unicode on the new Debian bookworm.
434# but even building the SAME SOURCE from scratch, somehow it doesn't on Ubuntu 8.
435# TBH I should probably just upgrade the mksh version.
436#
437# $ ./mksh -c 'printf "%u\n" \"$1' dummy $'\u03bc'
438# printf: warning: : character(s) following character constant have been ignored
439# 206
440#
441# andy@lenny:~/wedge/oils-for-unix.org/pkg/mksh/R52c$ cat /etc/os-release
442# NAME="Ubuntu"
443# VERSION="18.04.5 LTS (Bionic Beaver)"
444# ID=ubuntu
445# ID_LIKE=debian
446# PRETTY_NAME="Ubuntu 18.04.5 LTS"
447# VERSION_ID="18.04"
448# HOME_URL="https://www.ubuntu.com/"
449# SUPPORT_URL="https://help.ubuntu.com/"
450# BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
451# PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
452# VERSION_CODENAME=bionic
453# UBUNTU_CODENAME=bionic
454# andy@lenny:~/wedge/oils-for-unix.org/pkg/mksh/R52c$ env|egrep 'LC|LANG'
455# LANG=en_US.UTF-8
456# andy@lenny:~/wedge/oils-for-unix.org/pkg/mksh/R52c$ LC_CTYPE=C.UTF-8 ./mksh -c 'printf "%u\n" \"$1' dummy $'\u03bc'
457# printf: warning: : character(s) following character constant have been ignored
458# 206
459# andy@lenny:~/wedge/oils-for-unix.org/pkg/mksh/R52c$ LANG=C.UTF-8 ./mksh -c 'printf "%u\n" \"$1' dummy $'\u03bc'
460# printf: warning: : character(s) following character constant have been ignored
461# 206
462# andy@lenny:~/wedge/oils-for-unix.org/pkg/mksh/R52c$ LC_ALL=C.UTF-8 ./mksh -c 'printf "%u\n" \"$1' dummy $'\u03bc'
463# printf: warning: : character(s) following character constant have been ignored
464# 206
465# andy@lenny:~/wedge/oils-for-unix.org/pkg/mksh/R52c$ LC_ALL=en_US.UTF-8 ./mksh -c 'printf "%u\n" \"$1' dummy $'\u03bc'
466# printf: warning: : character(s) following character constant have been ignored
467# 206
468# andy@lenny:~/wedge/oils-for-unix.org/pkg/mksh/R52c$ LC_ALL=en_US.utf-8 ./mksh -c 'printf "%u\n" \"$1' dummy $'\u03bc'
469# printf: warning: : character(s) following character constant have been ignored
470# 206
471
472
473## STDOUT:
4743bc
475956
4761674
477
4784e09
47919977
48047011
481
482## END
483## BUG dash/ash STDOUT:
484ce
485206
486316
487
488e4
489228
490344
491
492## END
493
494## BUG mksh STDOUT:
495weird bug
496## END
497
498#### Invalid UTF-8
499
500echo bytes1
501not_utf8=$(python2 -c 'print("\xce\xce")')
502
503printf '%x\n' \'$not_utf8
504printf '%u\n' \'$not_utf8
505printf '%o\n' \'$not_utf8
506echo
507
508echo bytes2
509not_utf8=$(python2 -c 'print("\xbc\xbc")')
510printf '%x\n' \'$not_utf8
511printf '%u\n' \'$not_utf8
512printf '%o\n' \'$not_utf8
513echo
514
515# Copied from data_lang/utf8_test.cc
516
517echo overlong2
518overlong2=$(python2 -c 'print("\xC1\x81")')
519printf '%x\n' \'$overlong2
520printf '%u\n' \'$overlong2
521printf '%o\n' \'$overlong2
522echo
523
524echo overlong3
525overlong3=$(python2 -c 'print("\xE0\x81\x81")')
526printf '%x\n' \'$overlong3
527printf '%u\n' \'$overlong3
528printf '%o\n' \'$overlong3
529echo
530
531## STDOUT:
532bytes1
533ce
534206
535316
536
537bytes2
538bc
539188
540274
541
542overlong2
543c1
544193
545301
546
547overlong3
548e0
549224
550340
551
552## END
553
554
555#### Too large
556case $SH in mksh) echo 'weird bug'; exit ;; esac
557
558echo too large
559too_large=$(python2 -c 'print("\xF4\x91\x84\x91")')
560printf '%x\n' \'$too_large
561printf '%u\n' \'$too_large
562printf '%o\n' \'$too_large
563echo
564
565## STDOUT:
566too large
567111111
5681118481
5694210421
570
571## END
572
573## BUG dash/ash STDOUT:
574too large
575f4
576244
577364
578
579## END
580
581## BUG mksh STDOUT:
582weird bug
583## END
584
585# osh rejects code points that are too large for a DIFFERENT reason
586
587## OK osh STDOUT:
588too large
589f4
590244
591364
592
593## END
594
595
596#### negative numbers with unsigned / octal / hex
597printf '[%u]\n' -42
598printf '[%o]\n' -42
599printf '[%x]\n' -42
600printf '[%X]\n' -42
601## STDOUT:
602[18446744073709551574]
603[1777777777777777777726]
604[ffffffffffffffd6]
605[FFFFFFFFFFFFFFD6]
606## END
607
608# osh DISALLOWS this because the output depends on the machine architecture.
609## N-I osh stdout-json: ""
610## N-I osh status: 1
611
612#### printf floating point (not required, but they all implement it)
613printf '[%f]\n' 3.14159
614printf '[%.2f]\n' 3.14159
615printf '[%8.2f]\n' 3.14159
616printf '[%-8.2f]\n' 3.14159
617printf '[%-f]\n' 3.14159
618printf '[%-f]\n' 3.14
619## STDOUT:
620[3.141590]
621[3.14]
622[ 3.14]
623[3.14 ]
624[3.141590]
625[3.140000]
626## END
627## N-I osh stdout-json: ""
628## N-I osh status: 2
629
630#### printf floating point with - and 0
631printf '[%8.4f]\n' 3.14
632printf '[%08.4f]\n' 3.14
633printf '[%8.04f]\n' 3.14 # meaning less 0
634printf '[%08.04f]\n' 3.14
635echo ---
636# these all boil down to the same thing. The -, 8, and 4 are respected, but
637# none of the 0 are.
638printf '[%-8.4f]\n' 3.14
639printf '[%-08.4f]\n' 3.14
640printf '[%-8.04f]\n' 3.14
641printf '[%-08.04f]\n' 3.14
642## STDOUT:
643[ 3.1400]
644[003.1400]
645[ 3.1400]
646[003.1400]
647---
648[3.1400 ]
649[3.1400 ]
650[3.1400 ]
651[3.1400 ]
652## END
653## N-I osh STDOUT:
654---
655## END
656## N-I osh status: 2
657
658#### printf eE fF gG
659printf '[%e]\n' 3.14
660printf '[%E]\n' 3.14
661printf '[%f]\n' 3.14
662# bash is the only one that implements %F? Is it a synonym?
663#printf '[%F]\n' 3.14
664printf '[%g]\n' 3.14
665printf '[%G]\n' 3.14
666## STDOUT:
667[3.140000e+00]
668[3.140000E+00]
669[3.140000]
670[3.14]
671[3.14]
672## END
673## N-I osh stdout-json: ""
674## N-I osh status: 2
675
676#### printf backslash escapes
677argv.py "$(printf 'a\tb')"
678argv.py "$(printf '\xE2\x98\xA0')"
679argv.py "$(printf '\044e')"
680argv.py "$(printf '\0377')" # out of range
681## STDOUT:
682['a\tb']
683['\xe2\x98\xa0']
684['$e']
685['\x1f7']
686## END
687## N-I dash STDOUT:
688['a\tb']
689['\\xE2\\x98\\xA0']
690['$e']
691['\x1f7']
692## END
693
694#### printf octal backslash escapes
695argv.py "$(printf '\0377')"
696argv.py "$(printf '\377')"
697## STDOUT:
698['\x1f7']
699['\xff']
700## END
701
702#### printf unicode backslash escapes
703argv.py "$(printf '\u2620')"
704argv.py "$(printf '\U0000065f')"
705## STDOUT:
706['\xe2\x98\xa0']
707['\xd9\x9f']
708## END
709## N-I dash/ash STDOUT:
710['\\u2620']
711['\\U0000065f']
712## END
713
714#### printf invalid backslash escape (is ignored)
715printf '[\Z]\n'
716## STDOUT:
717[\Z]
718## END
719
720#### printf % escapes
721printf '[%%]\n'
722## STDOUT:
723[%]
724## END
725
726#### printf %b backslash escaping
727printf '[%s]\n' '\044' # escapes not evaluated
728printf '[%b]\n' '\044' # YES, escapes evaluated
729echo status=$?
730## STDOUT:
731[\044]
732[$]
733status=0
734## END
735
736#### printf %b with \c early return
737printf '[%b]\n' 'ab\ncd\cxy'
738echo $?
739## STDOUT:
740[ab
741cd0
742## END
743
744#### printf %c -- doesn't respect UTF-8! Bad.
745twomu=$'\u03bc\u03bc'
746printf '[%s]\n' "$twomu"
747printf '%c' "$twomu" | wc --bytes
748## STDOUT:
749[μμ]
7501
751## END
752## N-I dash STDOUT:
753[$\u03bc\u03bc]
7541
755## END
756## N-I ash STDOUT:
757[\u03bc\u03bc]
7581
759## END
760## N-I osh STDOUT:
761[μμ]
7620
763## END
764
765#### printf invalid format
766printf '%z' 42
767echo status=$?
768printf '%-z' 42
769echo status=$?
770## STDOUT:
771status=1
772status=1
773## END
774# osh emits parse errors
775## OK dash/osh STDOUT:
776status=2
777status=2
778## END
779
780#### printf %q
781x='a b'
782printf '[%q]\n' "$x"
783## STDOUT:
784['a b']
785## END
786## OK bash/zsh STDOUT:
787[a\ b]
788## END
789## N-I ash/dash stdout-json: "["
790## N-I ash status: 1
791## N-I dash status: 2
792
793#### printf %6q (width)
794# NOTE: coreutils /usr/bin/printf does NOT implement this %6q !!!
795x='a b'
796printf '[%6q]\n' "$x"
797printf '[%1q]\n' "$x"
798## STDOUT:
799[ 'a b']
800['a b']
801## END
802## OK bash/zsh STDOUT:
803[ a\ b]
804[a\ b]
805## END
806## N-I mksh/ash/dash stdout-json: "[["
807## N-I mksh/ash status: 1
808## N-I dash status: 2
809
810#### printf negative numbers
811printf '[%d] ' -42
812echo status=$?
813printf '[%i] ' -42
814echo status=$?
815
816# extra LEADING space too
817printf '[%d] ' ' -42'
818echo status=$?
819printf '[%i] ' ' -42'
820echo status=$?
821
822# extra TRAILING space too
823printf '[%d] ' ' -42 '
824echo status=$?
825printf '[%i] ' ' -42 '
826echo status=$?
827
828# extra TRAILING chars
829printf '[%d] ' ' -42z'
830echo status=$?
831printf '[%i] ' ' -42z'
832echo status=$?
833
834exit 0 # ok
835
836## STDOUT:
837[-42] status=0
838[-42] status=0
839[-42] status=0
840[-42] status=0
841[-42] status=1
842[-42] status=1
843[-42] status=1
844[-42] status=1
845## END
846# zsh is LESS STRICT
847## OK zsh STDOUT:
848[-42] status=0
849[-42] status=0
850[-42] status=0
851[-42] status=0
852[-42] status=0
853[-42] status=0
854[0] status=1
855[0] status=1
856## END
857
858# osh is like zsh but has a hard failure (TODO: could be an option?)
859## OK osh STDOUT:
860[-42] status=0
861[-42] status=0
862[-42] status=0
863[-42] status=0
864[-42] status=0
865[-42] status=0
866status=1
867status=1
868## END
869
870# ash is MORE STRICT
871## OK ash STDOUT:
872[-42] status=0
873[-42] status=0
874[-42] status=0
875[-42] status=0
876[0] status=1
877[0] status=1
878[0] status=1
879[0] status=1
880## END
881
882
883#### printf + and space flags
884# I didn't know these existed -- I only knew about - and 0 !
885printf '[%+d]\n' 42
886printf '[%+d]\n' -42
887printf '[% d]\n' 42
888printf '[% d]\n' -42
889## STDOUT:
890[+42]
891[-42]
892[ 42]
893[-42]
894## END
895## N-I osh stdout-json: ""
896## N-I osh status: 2
897
898#### printf # flag
899# I didn't know these existed -- I only knew about - and 0 !
900# Note: '#' flag for integers outputs a prefix ONLY WHEN the value is non-zero
901printf '[%#o][%#o]\n' 0 42
902printf '[%#x][%#x]\n' 0 42
903printf '[%#X][%#X]\n' 0 42
904echo ---
905# Note: '#' flag for %f, %g always outputs the decimal point.
906printf '[%.0f][%#.0f]\n' 3 3
907# Note: In addition, '#' flag for %g does not omit zeroes in fraction
908printf '[%g][%#g]\n' 3 3
909## STDOUT:
910[0][052]
911[0][0x2a]
912[0][0X2A]
913---
914[3][3.]
915[3][3.00000]
916## END
917## N-I osh STDOUT:
918---
919## END
920## N-I osh status: 2
921
922#### Runtime error for invalid integer
923x=3abc
924printf '%d\n' $x
925echo status=$?
926printf '%d\n' xyz
927echo status=$?
928## STDOUT:
9293
930status=1
9310
932status=1
933## END
934# zsh should exit 1 in both cases
935## BUG zsh STDOUT:
9360
937status=1
9380
939status=0
940## END
941# fails but also prints 0 instead of 3abc
942## BUG ash STDOUT:
9430
944status=1
9450
946status=1
947## END
948# osh doesn't print anything invalid
949## OK osh STDOUT:
950status=1
951status=1
952## END
953
954#### %(strftime format)T
955# The result depends on timezone
956export TZ=Asia/Tokyo
957printf '%(%Y-%m-%d)T\n' 1557978599
958export TZ=US/Eastern
959printf '%(%Y-%m-%d)T\n' 1557978599
960echo status=$?
961## STDOUT:
9622019-05-16
9632019-05-15
964status=0
965## END
966## N-I mksh/zsh/ash STDOUT:
967status=1
968## END
969## N-I dash STDOUT:
970status=2
971## END
972
973#### %(strftime format)T doesn't respect TZ if not exported
974
975# note: this test leaks! It assumes that /etc/localtime is NOT Portugal.
976
977TZ=Portugal # NOT exported
978localtime=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599)
979
980# TZ is respected
981export TZ=Portugal
982tz=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599)
983
984#echo $localtime
985#echo $tz
986
987if ! test "$localtime" = "$tz"; then
988 echo 'not equal'
989fi
990## STDOUT:
991not equal
992## END
993## N-I mksh/zsh/ash/dash stdout-json: ""
994
995#### %(strftime format)T TZ in environ but not in shell's memory
996
997# note: this test leaks! It assumes that /etc/localtime is NOT Portugal.
998
999# TZ is respected
1000export TZ=Portugal
1001tz=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599)
1002
1003unset TZ # unset in the shell, but still in the environment
1004
1005localtime=$(printf '%(%Y-%m-%d %H:%M:%S)T\n' 1557978599)
1006
1007if ! test "$localtime" = "$tz"; then
1008 echo 'not equal'
1009fi
1010
1011## STDOUT:
1012not equal
1013## END
1014## N-I mksh/zsh/ash/dash stdout-json: ""
1015
1016#### %10.5(strftime format)T
1017# The result depends on timezone
1018export TZ=Asia/Tokyo
1019printf '[%10.5(%Y-%m-%d)T]\n' 1557978599
1020export TZ=US/Eastern
1021printf '[%10.5(%Y-%m-%d)T]\n' 1557978599
1022echo status=$?
1023## STDOUT:
1024[ 2019-]
1025[ 2019-]
1026status=0
1027## END
1028## N-I dash/mksh/zsh/ash STDOUT:
1029[[status=1
1030## END
1031## N-I dash STDOUT:
1032[[status=2
1033## END
1034
1035#### Regression for 'printf x y'
1036printf x y
1037printf '%s\n' z
1038## STDOUT:
1039xz
1040## END
1041
1042#### bash truncates long strftime string at 128
1043
1044case $SH in (ash|dash|mksh|zsh) exit ;; esac
1045
1046strftime-format() {
1047 local n=$1
1048
1049 # Prints increasingly long format strings:
1050 # %(%Y)T %(%Y)T %(%Y%Y)T ...
1051
1052 echo -n '%('
1053 for i in $(seq $n); do
1054 echo -n '%Y'
1055 done
1056 echo -n ')T'
1057}
1058
1059printf $(strftime-format 1) | wc --bytes
1060printf $(strftime-format 10) | wc --bytes
1061printf $(strftime-format 30) | wc --bytes
1062printf $(strftime-format 31) | wc --bytes
1063printf $(strftime-format 32) | wc --bytes
1064
1065case $SH in
1066 (*/_bin/cxx-dbg/*)
1067 # Ensure that oils-for-unix detects the truncation of a fixed buffer.
1068 # bash has a buffer of 128.
1069
1070 set +o errexit
1071 (
1072 printf $(strftime-format 1000)
1073 )
1074 status=$?
1075 if test $status -ne 1; then
1076 echo FAIL
1077 fi
1078 ;;
1079esac
1080
1081## STDOUT:
10824
108340
1084120
1085124
10860
1087## END
1088## OK osh STDOUT:
10894
109040
1091120
1092124
1093128
1094## END
1095
1096## N-I ash/dash/mksh/zsh STDOUT:
1097## END
1098
1099
1100#### printf with explicit NUL byte
1101case $SH in (dash|ash) return ;; esac
1102
1103printf $'x\U0z'
1104
1105printf $'\U0z'
1106
1107## stdout-json: "x"
1108## OK zsh stdout-repr: "x\0z\0z"
1109## N-I dash/ash stdout-json: ""
1110
1111#### printf positive integer overflow
1112
1113# %i seems like a synonym for %d
1114
1115for fmt in '%u\n' '%d\n'; do
1116 # bash considers this in range for %u
1117 # same with mksh
1118 # zsh cuts everything off after 19 digits
1119 # ash truncates everything
1120 printf "$fmt" '18446744073709551615'
1121 printf "$fmt" '18446744073709551616'
1122 echo
1123done
1124
1125## status: 1
1126## STDOUT:
1127## END
1128
1129## OK bash/dash/mksh status: 0
1130## OK bash/dash/mksh STDOUT:
113118446744073709551615
113218446744073709551615
1133
11349223372036854775807
11359223372036854775807
1136
1137## END
1138
1139## BUG ash status: 0
1140## BUG ash STDOUT:
114118446744073709551615
11420
1143
11440
11450
1146
1147## END
1148
1149## BUG zsh status: 0
1150## BUG zsh STDOUT:
11511844674407370955161
11521844674407370955161
1153
11541844674407370955161
11551844674407370955161
1156
1157## END
1158
1159#### printf negative integer overflow
1160
1161# %i seems like a synonym for %d
1162
1163for fmt in '%u\n' '%d\n'; do
1164
1165 #printf "$fmt" '-9223372036854775806'
1166 #printf "$fmt" '-9223372036854775807'
1167 #printf "$fmt" '-9223372036854775808'
1168
1169 printf "$fmt" '-18446744073709551615'
1170 printf "$fmt" '-18446744073709551616'
1171 echo
1172done
1173
1174## status: 1
1175## STDOUT:
1176## END
1177
1178## OK bash/dash/mksh status: 0
1179## OK bash/dash/mksh STDOUT:
11801
118118446744073709551615
1182
1183-9223372036854775808
1184-9223372036854775808
1185
1186## END
1187
1188## BUG zsh status: 0
1189## BUG zsh STDOUT:
119016602069666338596455
119116602069666338596455
1192
1193-1844674407370955161
1194-1844674407370955161
1195
1196## END
1197
1198## BUG ash status: 0
1199## BUG ash STDOUT:
12000
12010
1202
12030
12040
1205
1206## END
1207