################################################################################
##
##  Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz.
##  Version 2.x, Copyright (C) 2001, Paul Marquess.
##  Version 1.x, Copyright (C) 1999, Kenneth Albanowski.
##
##  This program is free software; you can redistribute it and/or
##  modify it under the same terms as Perl itself.
##
################################################################################

=provides

/^#\s*define\s+(\w+)/

=implementation

#ifndef IVdf
#  if IVSIZE == LONGSIZE
#    define     IVdf      "ld"
#    define     UVuf      "lu"
#    define     UVof      "lo"
#    define     UVxf      "lx"
#    define     UVXf      "lX"
#  elif IVSIZE == INTSIZE
#    define   IVdf      "d"
#    define   UVuf      "u"
#    define   UVof      "o"
#    define   UVxf      "x"
#    define   UVXf      "X"
#  else
#    error "cannot define IV/UV formats"
#  endif
#endif

#ifndef NVef
#  if defined(USE_LONG_DOUBLE) && defined(HAS_LONG_DOUBLE) && \
      defined(PERL_PRIfldbl) && { VERSION != 5.6.0 }
            /* Not very likely, but let's try anyway. */
#    define NVef          PERL_PRIeldbl
#    define NVff          PERL_PRIfldbl
#    define NVgf          PERL_PRIgldbl
#  else
#    define NVef          "e"
#    define NVff          "f"
#    define NVgf          "g"
#  endif
#endif

=xsubs

void
croak_NVgf(num)
        NV num
        PPCODE:
                Perl_croak(aTHX_ "%.20" NVgf "\n", num);

#if { VERSION >= 5.004 }

SV *
sprintf_iv(iv)
        IV iv
CODE:
        RETVAL = newSVpvf("XX_%" IVdf "_XX", iv);
OUTPUT:
        RETVAL

SV *
sprintf_uv(uv)
        UV uv
CODE:
        RETVAL = newSVpvf("XX_%" UVuf "_XX", uv);
OUTPUT:
        RETVAL

SV *
sprintf_ivmax()
CODE:
        RETVAL = newSVpvf("%" IVdf, IV_MAX);
OUTPUT:
        RETVAL

SV *
sprintf_uvmax()
CODE:
        RETVAL = newSVpvf("%" UVuf, UV_MAX);
OUTPUT:
        RETVAL

#endif

=tests plan => 5

use Config;

if ("$]" < '5.004') {
    skip 'skip: No newSVpvf support', 5;
    exit;
}

my $num = 1.12345678901234567890;

eval { Devel::PPPort::croak_NVgf($num) };
ok($@ =~ /^1.1234567890/);

is(Devel::PPPort::sprintf_iv(-8), 'XX_-8_XX');
is(Devel::PPPort::sprintf_uv(15), 'XX_15_XX');

my $ivsize = $Config::Config{ivsize};
if ($ivsize && ($ivsize == 4 || $ivsize == 8)) {
    my $ivmax = ($ivsize == 4) ? '2147483647' : '9223372036854775807';
    my $uvmax = ($ivsize == 4) ? '4294967295' : '18446744073709551615';
    is(Devel::PPPort::sprintf_ivmax(), $ivmax);
    is(Devel::PPPort::sprintf_uvmax(), $uvmax);
}
else {
    skip 'skip: unknown ivsize', 2;
}
