In perl.git, the branch blead has been updated <http://perl5.git.perl.org/perl.git/commitdiff/f6166f76b7f5b59becd71ea9d8f959a789ee70f8?hp=d5fbd9dd00e27f435423fd4898ed0e5804de0fd6>
- Log ----------------------------------------------------------------- commit f6166f76b7f5b59becd71ea9d8f959a789ee70f8 Author: Chip Salzenberg <c...@pobox.com> Date: Fri Dec 17 10:55:20 2010 -0800 document new printf size modifiers M pod/perldelta.pod commit 673c2ba8988082a3225a61fc6a54304514e378e7 Author: Chip Salzenberg <c...@pobox.com> Date: Fri Dec 17 10:46:56 2010 -0800 smoke tests for %hhd %zd %td M t/op/sprintf.t commit 07208e09d4435b4e72743076e0bc290ef4b34911 Author: Chip Salzenberg <c...@pobox.com> Date: Fri Dec 17 10:13:43 2010 -0800 add %jd to printf where C99 exists; tweak %zd and %td M sv.c ----------------------------------------------------------------------- Summary of changes: pod/perldelta.pod | 9 ++++++++ sv.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++----- t/op/sprintf.t | 7 ++++- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/pod/perldelta.pod b/pod/perldelta.pod index 835d706..630ccc0 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -109,6 +109,15 @@ This double setting arrangement is a stopgap until the reason for unwinding can be made properly introspectable. C<$@> has never been a reliable indicator of this. +=head2 printf-like functions understand size modifiers "hh", "z", "t", and sometimes "j" + +Perl's printf and sprintf operators, and Perl's internal printf replacement +function, now understand the C90 size modifiers "hh" (C<char>), "z" +(C<size_t>), and "t" (C<ptrdiff_t>). Also, when compiled with a C99 +compiler, Perl now understands the size modifier "j" (C<intmax_t>). + +So, for example, on any modern machine, C<sprintf('%hhd', 257)> returns '1'. + =head2 DTrace probes now include package name The DTrace probes now include an additional argument (C<arg3>) which contains diff --git a/sv.c b/sv.c index 4371375..99433b0 100644 --- a/sv.c +++ b/sv.c @@ -32,6 +32,15 @@ #include "perl.h" #include "regcomp.h" +#ifndef HAS_C99 +# if __STDC_VERSION__ >= 199901L +# define HAS_C99 1 +# endif +#endif +#if HAS_C99 +# include <stdint.h> +#endif + #define FCALL *f #ifdef __Lynx__ @@ -10270,16 +10279,28 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, #endif case 'l': #if defined(HAS_QUAD) || defined(HAS_LONG_DOUBLE) - if (*(q + 1) == 'l') { /* lld, llf */ + if (*++q == 'l') { /* lld, llf */ intsize = 'q'; - q += 2; - break; - } + ++q; + } + else #endif - /*FALLTHROUGH*/ + intsize = 'l'; + break; case 'h': - /*FALLTHROUGH*/ + if (*++q == 'h') { /* hhd, hhu */ + intsize = 'c'; + ++q; + } + else + intsize = 'h'; + break; case 'V': + case 'z': + case 't': +#if HAS_C99 + case 'j': +#endif intsize = *q++; break; } @@ -10405,10 +10426,16 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, } else if (args) { switch (intsize) { + case 'c': iv = (char)va_arg(*args, int); break; case 'h': iv = (short)va_arg(*args, int); break; case 'l': iv = va_arg(*args, long); break; case 'V': iv = va_arg(*args, IV); break; + case 'z': iv = va_arg(*args, SSize_t); break; + case 't': iv = va_arg(*args, ptrdiff_t); break; default: iv = va_arg(*args, int); break; +#if HAS_C99 + case 'j': iv = va_arg(*args, intmax_t); break; +#endif case 'q': #ifdef HAS_QUAD iv = va_arg(*args, Quad_t); break; @@ -10420,6 +10447,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, else { IV tiv = SvIV(argsv); /* work around GCC bug #13488 */ switch (intsize) { + case 'c': iv = (char)tiv; break; case 'h': iv = (short)tiv; break; case 'l': iv = (long)tiv; break; case 'V': @@ -10496,9 +10524,15 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, } else if (args) { switch (intsize) { + case 'c': uv = (unsigned char)va_arg(*args, unsigned); break; case 'h': uv = (unsigned short)va_arg(*args, unsigned); break; case 'l': uv = va_arg(*args, unsigned long); break; case 'V': uv = va_arg(*args, UV); break; + case 'z': uv = va_arg(*args, Size_t); break; + case 't': uv = va_arg(*args, ptrdiff_t); break; /* will sign extend, but there is no uptrdiff_t, so oh well */ +#if HAS_C99 + case 'j': uv = va_arg(*args, uintmax_t); break; +#endif default: uv = va_arg(*args, unsigned); break; case 'q': #ifdef HAS_QUAD @@ -10511,6 +10545,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, else { UV tuv = SvUV(argsv); /* work around GCC bug #13488 */ switch (intsize) { + case 'c': uv = (unsigned char)tuv; break; case 'h': uv = (unsigned short)tuv; break; case 'l': uv = (unsigned long)tuv; break; case 'V': @@ -10621,7 +10656,11 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, #else /*FALLTHROUGH*/ #endif + case 'c': case 'h': + case 'z': + case 't': + case 'j': goto unknown; } @@ -10801,10 +10840,16 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen, i = SvCUR(sv) - origlen; if (args) { switch (intsize) { + case 'c': *(va_arg(*args, char*)) = i; break; case 'h': *(va_arg(*args, short*)) = i; break; default: *(va_arg(*args, int*)) = i; break; case 'l': *(va_arg(*args, long*)) = i; break; case 'V': *(va_arg(*args, IV*)) = i; break; + case 'z': *(va_arg(*args, SSize_t*)) = i; break; + case 't': *(va_arg(*args, ptrdiff_t*)) = i; break; +#if HAS_C99 + case 'j': *(va_arg(*args, intmax_t*)) = i; break; +#endif case 'q': #ifdef HAS_QUAD *(va_arg(*args, Quad_t*)) = i; break; diff --git a/t/op/sprintf.t b/t/op/sprintf.t index 14f0395..54f3c2b 100644 --- a/t/op/sprintf.t +++ b/t/op/sprintf.t @@ -301,8 +301,11 @@ __END__ >% 3d< >-1< > -1< >%03d< >-1< >-01< >%hd< >1< >1< >More extensive testing of< ->%ld< >1< >1< >length modifiers would be< ->%Vd< >1< >1< >platform-specific< +>%hhd< >1< >1< >length modifiers would be< +>%ld< >1< >1< >platform-specific< +>%Vd< >1< >1< +>%zd< >1< >1< +>%td< >1< >1< >%vd< >chr(1)< >1< >%+vd< >chr(1)< >+1< >%#vd< >chr(1)< >1< -- Perl5 Master Repository