#define PACK_SIZE_UNPREDICTABLE 0x40 /* Not a fixed size element */
#define PACK_SIZE_MASK 0x3F
-#include "packsizetables.c"
+#include "packsizetables.inc"
static void
S_reverse_copy(const char *src, char *dest, STRLEN len)
}
STATIC char *
-S_bytes_to_utf8(const U8 *start, STRLEN len, char *dest, const bool needs_swap) {
- PERL_ARGS_ASSERT_BYTES_TO_UNI;
+S_my_bytes_to_utf8(const U8 *start, STRLEN len, char *dest, const bool needs_swap) {
+ PERL_ARGS_ASSERT_MY_BYTES_TO_UTF8;
if (UNLIKELY(needs_swap)) {
const U8 *p = start + len;
#define PUSH_BYTES(utf8, cur, buf, len, needs_swap) \
STMT_START { \
if (UNLIKELY(utf8)) \
- (cur) = S_bytes_to_utf8((U8 *) buf, len, (cur), needs_swap); \
+ (cur) = my_bytes_to_utf8((U8 *) buf, len, (cur), needs_swap); \
else { \
if (UNLIKELY(needs_swap)) \
S_reverse_copy((char *)(buf), cur, len); \
STMT_START { \
if (utf8) { \
const U8 au8 = (byte); \
- (s) = S_bytes_to_utf8(&au8, 1, (s), 0); \
+ (s) = my_bytes_to_utf8(&au8, 1, (s), 0);\
} else *(U8 *)(s)++ = (byte); \
} STMT_END
=for apidoc unpackstring
-The engine implementing the unpack() Perl function.
+The engine implementing the C<unpack()> Perl function.
-Using the template pat..patend, this function unpacks the string
-s..strend into a number of mortal SVs, which it pushes onto the perl
-argument (@_) stack (so you will need to issue a C<PUTBACK> before and
+Using the template C<pat..patend>, this function unpacks the string
+C<s..strend> into a number of mortal SVs, which it pushes onto the perl
+argument (C<@_>) stack (so you will need to issue a C<PUTBACK> before and
C<SPAGAIN> after the call to this function). It returns the number of
pushed elements.
-The strend and patend pointers should point to the byte following the last
-character of each string.
+The C<strend> and C<patend> pointers should point to the byte following the
+last character of each string.
Although this function returns its values on the perl argument stack, it
doesn't take any parameters from that stack (and thus in particular
-there's no need to do a PUSHMARK before calling it, unlike L</call_pv> for
+there's no need to do a C<PUSHMARK> before calling it, unlike L</call_pv> for
example).
=cut */
U8 ch;
ch = SHIFT_BYTE(utf8, s, strend, datumtype);
auv = (auv << 7) | (ch & 0x7f);
- /* UTF8_IS_XXXXX not right here - using constant 0x80 */
+ /* UTF8_IS_XXXXX not right here because this is a BER, not
+ * UTF-8 format - using constant 0x80 */
if (ch < 0x80) {
bytes = 0;
mPUSHu(auv);
}
while (cdouble < 0.0)
cdouble += anv;
- cdouble = Perl_modf(cdouble / anv, &trouble) * anv;
+ cdouble = Perl_modf(cdouble / anv, &trouble);
+#ifdef LONGDOUBLE_DOUBLEDOUBLE
+ /* Workaround for powerpc doubledouble modfl bug:
+ * close to 1.0L and -1.0L cdouble is 0, and trouble
+ * is cdouble / anv. */
+ if (trouble != Perl_ceil(trouble)) {
+ cdouble = trouble;
+ if (cdouble > 1.0L) cdouble -= 1.0L;
+ if (cdouble < -1.0L) cdouble += 1.0L;
+ }
+#endif
+ cdouble *= anv;
sv = newSVnv(cdouble);
}
else {
{
dSP;
dPOPPOPssrl;
- I32 gimme = GIMME_V;
+ U8 gimme = GIMME_V;
STRLEN llen;
STRLEN rlen;
const char *pat = SvPV_const(left, llen);
/*
=for apidoc packlist
-The engine implementing pack() Perl function.
+The engine implementing C<pack()> Perl function.
=cut
*/
if (howlen == e_star) len = fromlen;
field_len = (len+1)/2;
GROWING(utf8, cat, start, cur, field_len);
- if (!utf8 && len > (I32)fromlen) len = fromlen;
+ if (!utf8_source && len > (I32)fromlen) len = fromlen;
bits = 0;
l = 0;
if (datumtype == 'H')
len+(endb-buffer)*UTF8_EXPAND);
end = start+SvLEN(cat);
}
- cur = S_bytes_to_utf8(buffer, endb-buffer, cur, 0);
+ cur = my_bytes_to_utf8(buffer, endb-buffer, cur, 0);
} else {
if (cur >= end) {
*cur = '\0';
afloat = -FLT_MAX;
else afloat = (float)anv;
# else
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ if(Perl_isnan(anv))
+ afloat = (float)NV_NAN;
+ else
+#endif
/* a simple cast to float is undefined if outside
* the range of values that can be represented */
afloat = (float)(anv > FLT_MAX ? NV_INF :
#ifdef __GNUC__
/* to work round a gcc/x86 bug; don't use SvNV */
anv.nv = sv_2nv(fromstr);
+# if defined(LONGDOUBLE_X86_80_BIT) && defined(USE_LONG_DOUBLE) \
+ && LONG_DOUBLESIZE > 10
+ /* GCC sometimes overwrites the padding in the
+ assignment above */
+ Zero(anv.bytes+10, sizeof(anv.bytes) - 10, U8);
+# endif
#else
anv.nv = SvNV(fromstr);
#endif
# ifdef __GNUC__
/* to work round a gcc/x86 bug; don't use SvNV */
aldouble.ld = (long double)sv_2nv(fromstr);
+# if defined(LONGDOUBLE_X86_80_BIT) && LONG_DOUBLESIZE > 10
+ /* GCC sometimes overwrites the padding in the
+ assignment above */
+ Zero(aldouble.bytes+10, sizeof(aldouble.bytes) - 10, U8);
+# endif
# else
aldouble.ld = (long double)SvNV(fromstr);
# endif
}
/*
- * Local variables:
- * c-indentation-style: bsd
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- *
* ex: set ts=8 sts=4 sw=4 et:
*/