Apd |SV* |hv_scalar |HV* hv|
p |SV* |magic_scalarpack|HV* hv|MAGIC* mg
+#ifdef PERL_NEED_MY_HTOLE16
+np |U16 |my_htole16 |U16 n
+#endif
+#ifdef PERL_NEED_MY_LETOH16
+np |U16 |my_letoh16 |U16 n
+#endif
+#ifdef PERL_NEED_MY_HTOBE16
+np |U16 |my_htobe16 |U16 n
+#endif
+#ifdef PERL_NEED_MY_BETOH16
+np |U16 |my_betoh16 |U16 n
+#endif
+#ifdef PERL_NEED_MY_HTOLE32
+np |U32 |my_htole32 |U32 n
+#endif
+#ifdef PERL_NEED_MY_LETOH32
+np |U32 |my_letoh32 |U32 n
+#endif
+#ifdef PERL_NEED_MY_HTOBE32
+np |U32 |my_htobe32 |U32 n
+#endif
+#ifdef PERL_NEED_MY_BETOH32
+np |U32 |my_betoh32 |U32 n
+#endif
+#ifdef PERL_NEED_MY_HTOLE64
+np |U64 |my_htole64 |U64 n
+#endif
+#ifdef PERL_NEED_MY_LETOH64
+np |U64 |my_letoh64 |U64 n
+#endif
+#ifdef PERL_NEED_MY_HTOBE64
+np |U64 |my_htobe64 |U64 n
+#endif
+#ifdef PERL_NEED_MY_BETOH64
+np |U64 |my_betoh64 |U64 n
+#endif
+
+#ifdef PERL_NEED_MY_HTOLES
+np |short |my_htoles |short n
+#endif
+#ifdef PERL_NEED_MY_LETOHS
+np |short |my_letohs |short n
+#endif
+#ifdef PERL_NEED_MY_HTOBES
+np |short |my_htobes |short n
+#endif
+#ifdef PERL_NEED_MY_BETOHS
+np |short |my_betohs |short n
+#endif
+#ifdef PERL_NEED_MY_HTOLEI
+np |int |my_htolei |int n
+#endif
+#ifdef PERL_NEED_MY_LETOHI
+np |int |my_letohi |int n
+#endif
+#ifdef PERL_NEED_MY_HTOBEI
+np |int |my_htobei |int n
+#endif
+#ifdef PERL_NEED_MY_BETOHI
+np |int |my_betohi |int n
+#endif
+#ifdef PERL_NEED_MY_HTOLEL
+np |long |my_htolel |long n
+#endif
+#ifdef PERL_NEED_MY_LETOHL
+np |long |my_letohl |long n
+#endif
+#ifdef PERL_NEED_MY_HTOBEL
+np |long |my_htobel |long n
+#endif
+#ifdef PERL_NEED_MY_BETOHL
+np |long |my_betohl |long n
+#endif
+
+np |void |my_swabn |void* ptr|int n
+
END_EXTERN_C
#ifdef PERL_CORE
#define magic_scalarpack Perl_magic_scalarpack
#endif
+#ifdef PERL_NEED_MY_HTOLE16
+#ifdef PERL_CORE
+#define my_htole16 Perl_my_htole16
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOH16
+#ifdef PERL_CORE
+#define my_letoh16 Perl_my_letoh16
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE16
+#ifdef PERL_CORE
+#define my_htobe16 Perl_my_htobe16
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOH16
+#ifdef PERL_CORE
+#define my_betoh16 Perl_my_betoh16
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLE32
+#ifdef PERL_CORE
+#define my_htole32 Perl_my_htole32
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOH32
+#ifdef PERL_CORE
+#define my_letoh32 Perl_my_letoh32
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE32
+#ifdef PERL_CORE
+#define my_htobe32 Perl_my_htobe32
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOH32
+#ifdef PERL_CORE
+#define my_betoh32 Perl_my_betoh32
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLE64
+#ifdef PERL_CORE
+#define my_htole64 Perl_my_htole64
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOH64
+#ifdef PERL_CORE
+#define my_letoh64 Perl_my_letoh64
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE64
+#ifdef PERL_CORE
+#define my_htobe64 Perl_my_htobe64
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOH64
+#ifdef PERL_CORE
+#define my_betoh64 Perl_my_betoh64
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLES
+#ifdef PERL_CORE
+#define my_htoles Perl_my_htoles
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOHS
+#ifdef PERL_CORE
+#define my_letohs Perl_my_letohs
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBES
+#ifdef PERL_CORE
+#define my_htobes Perl_my_htobes
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOHS
+#ifdef PERL_CORE
+#define my_betohs Perl_my_betohs
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLEI
+#ifdef PERL_CORE
+#define my_htolei Perl_my_htolei
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOHI
+#ifdef PERL_CORE
+#define my_letohi Perl_my_letohi
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBEI
+#ifdef PERL_CORE
+#define my_htobei Perl_my_htobei
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOHI
+#ifdef PERL_CORE
+#define my_betohi Perl_my_betohi
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLEL
+#ifdef PERL_CORE
+#define my_htolel Perl_my_htolel
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOHL
+#ifdef PERL_CORE
+#define my_letohl Perl_my_letohl
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBEL
+#ifdef PERL_CORE
+#define my_htobel Perl_my_htobel
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOHL
+#ifdef PERL_CORE
+#define my_betohl Perl_my_betohl
+#endif
+#endif
+#ifdef PERL_CORE
+#define my_swabn Perl_my_swabn
+#endif
#define ck_anoncode Perl_ck_anoncode
#define ck_bitop Perl_ck_bitop
#define ck_concat Perl_ck_concat
#ifdef PERL_CORE
#define magic_scalarpack(a,b) Perl_magic_scalarpack(aTHX_ a,b)
#endif
+#ifdef PERL_NEED_MY_HTOLE16
+#ifdef PERL_CORE
+#define my_htole16 Perl_my_htole16
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOH16
+#ifdef PERL_CORE
+#define my_letoh16 Perl_my_letoh16
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE16
+#ifdef PERL_CORE
+#define my_htobe16 Perl_my_htobe16
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOH16
+#ifdef PERL_CORE
+#define my_betoh16 Perl_my_betoh16
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLE32
+#ifdef PERL_CORE
+#define my_htole32 Perl_my_htole32
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOH32
+#ifdef PERL_CORE
+#define my_letoh32 Perl_my_letoh32
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE32
+#ifdef PERL_CORE
+#define my_htobe32 Perl_my_htobe32
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOH32
+#ifdef PERL_CORE
+#define my_betoh32 Perl_my_betoh32
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLE64
+#ifdef PERL_CORE
+#define my_htole64 Perl_my_htole64
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOH64
+#ifdef PERL_CORE
+#define my_letoh64 Perl_my_letoh64
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE64
+#ifdef PERL_CORE
+#define my_htobe64 Perl_my_htobe64
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOH64
+#ifdef PERL_CORE
+#define my_betoh64 Perl_my_betoh64
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLES
+#ifdef PERL_CORE
+#define my_htoles Perl_my_htoles
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOHS
+#ifdef PERL_CORE
+#define my_letohs Perl_my_letohs
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBES
+#ifdef PERL_CORE
+#define my_htobes Perl_my_htobes
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOHS
+#ifdef PERL_CORE
+#define my_betohs Perl_my_betohs
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLEI
+#ifdef PERL_CORE
+#define my_htolei Perl_my_htolei
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOHI
+#ifdef PERL_CORE
+#define my_letohi Perl_my_letohi
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBEI
+#ifdef PERL_CORE
+#define my_htobei Perl_my_htobei
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOHI
+#ifdef PERL_CORE
+#define my_betohi Perl_my_betohi
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOLEL
+#ifdef PERL_CORE
+#define my_htolel Perl_my_htolel
+#endif
+#endif
+#ifdef PERL_NEED_MY_LETOHL
+#ifdef PERL_CORE
+#define my_letohl Perl_my_letohl
+#endif
+#endif
+#ifdef PERL_NEED_MY_HTOBEL
+#ifdef PERL_CORE
+#define my_htobel Perl_my_htobel
+#endif
+#endif
+#ifdef PERL_NEED_MY_BETOHL
+#ifdef PERL_CORE
+#define my_betohl Perl_my_betohl
+#endif
+#endif
+#ifdef PERL_CORE
+#define my_swabn Perl_my_swabn
+#endif
#define ck_anoncode(a) Perl_ck_anoncode(aTHX_ a)
#define ck_bitop(a) Perl_ck_bitop(aTHX_ a)
#define ck_concat(a) Perl_ck_concat(aTHX_ a)
# define MYSWAP
#endif
+#ifdef PERL_CORE
+
+/* macros for correct constant construction */
+# if INTSIZE >= 2
+# define U16_CONST(x) ((U16)x##U)
+# else
+# define U16_CONST(x) ((U16)x##UL)
+# endif
+
+# if INTSIZE >= 4
+# define U32_CONST(x) ((U32)x##U)
+# else
+# define U32_CONST(x) ((U32)x##UL)
+# endif
+
+# ifdef HAS_QUAD
+# if INTSIZE >= 8
+# define U64_CONST(x) ((U64)x##U)
+# elif LONGSIZE >= 8
+# define U64_CONST(x) ((U64)x##UL)
+# elif QUADKIND == QUAD_IS_LONG_LONG
+# define U64_CONST(x) ((U64)x##ULL)
+# else /* best guess we can make */
+# define U64_CONST(x) ((U64)x##UL)
+# endif
+# endif
+
+/* byte-swapping functions for big-/little-endian conversion */
+# define _swab_16_(x) ((U16)( \
+ (((U16)(x) & U16_CONST(0x00ff)) << 8) | \
+ (((U16)(x) & U16_CONST(0xff00)) >> 8) ))
+
+# define _swab_32_(x) ((U32)( \
+ (((U32)(x) & U32_CONST(0x000000ff)) << 24) | \
+ (((U32)(x) & U32_CONST(0x0000ff00)) << 8) | \
+ (((U32)(x) & U32_CONST(0x00ff0000)) >> 8) | \
+ (((U32)(x) & U32_CONST(0xff000000)) >> 24) ))
+
+# ifdef HAS_QUAD
+# define _swab_64_(x) ((U64)( \
+ (((U64)(x) & U64_CONST(0x00000000000000ff)) << 56) | \
+ (((U64)(x) & U64_CONST(0x000000000000ff00)) << 40) | \
+ (((U64)(x) & U64_CONST(0x0000000000ff0000)) << 24) | \
+ (((U64)(x) & U64_CONST(0x00000000ff000000)) << 8) | \
+ (((U64)(x) & U64_CONST(0x000000ff00000000)) >> 8) | \
+ (((U64)(x) & U64_CONST(0x0000ff0000000000)) >> 24) | \
+ (((U64)(x) & U64_CONST(0x00ff000000000000)) >> 40) | \
+ (((U64)(x) & U64_CONST(0xff00000000000000)) >> 56) ))
+# endif
+
+/*----------------------------------------------------------------------------*/
+# if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 /* little-endian */
+/*----------------------------------------------------------------------------*/
+# define my_htole16(x) (x)
+# define my_letoh16(x) (x)
+# define my_htole32(x) (x)
+# define my_letoh32(x) (x)
+# define my_htobe16(x) _swab_16_(x)
+# define my_betoh16(x) _swab_16_(x)
+# define my_htobe32(x) _swab_32_(x)
+# define my_betoh32(x) _swab_32_(x)
+# ifdef HAS_QUAD
+# define my_htole64(x) (x)
+# define my_letoh64(x) (x)
+# define my_htobe64(x) _swab_64_(x)
+# define my_betoh64(x) _swab_64_(x)
+# endif
+# define my_htoles(x) (x)
+# define my_letohs(x) (x)
+# define my_htolei(x) (x)
+# define my_letohi(x) (x)
+# define my_htolel(x) (x)
+# define my_letohl(x) (x)
+# if SHORTSIZE == 1
+# define my_htobes(x) (x)
+# define my_betohs(x) (x)
+# elif SHORTSIZE == 2
+# define my_htobes(x) _swab_16_(x)
+# define my_betohs(x) _swab_16_(x)
+# elif SHORTSIZE == 4
+# define my_htobes(x) _swab_32_(x)
+# define my_betohs(x) _swab_32_(x)
+# elif SHORTSIZE == 8
+# define my_htobes(x) _swab_64_(x)
+# define my_betohs(x) _swab_64_(x)
+# else
+# define PERL_NEED_MY_HTOBES
+# define PERL_NEED_MY_BETOHS
+# endif
+# if INTSIZE == 1
+# define my_htobei(x) (x)
+# define my_betohi(x) (x)
+# elif INTSIZE == 2
+# define my_htobei(x) _swab_16_(x)
+# define my_betohi(x) _swab_16_(x)
+# elif INTSIZE == 4
+# define my_htobei(x) _swab_32_(x)
+# define my_betohi(x) _swab_32_(x)
+# elif INTSIZE == 8
+# define my_htobei(x) _swab_64_(x)
+# define my_betohi(x) _swab_64_(x)
+# else
+# define PERL_NEED_MY_HTOBEI
+# define PERL_NEED_MY_BETOHI
+# endif
+# if LONGSIZE == 1
+# define my_htobel(x) (x)
+# define my_betohl(x) (x)
+# elif LONGSIZE == 2
+# define my_htobel(x) _swab_16_(x)
+# define my_betohl(x) _swab_16_(x)
+# elif LONGSIZE == 4
+# define my_htobel(x) _swab_32_(x)
+# define my_betohl(x) _swab_32_(x)
+# elif LONGSIZE == 8
+# define my_htobel(x) _swab_64_(x)
+# define my_betohl(x) _swab_64_(x)
+# else
+# define PERL_NEED_MY_HTOBEL
+# define PERL_NEED_MY_BETOHL
+# endif
+# define my_htolen(p,n) NOOP
+# define my_letohn(p,n) NOOP
+# define my_htoben(p,n) my_swabn(p,n)
+# define my_betohn(p,n) my_swabn(p,n)
+/*----------------------------------------------------------------------------*/
+# elif BYTEORDER == 0x4321 || BYTEORDER == 0x87654321 /* big-endian */
+/*----------------------------------------------------------------------------*/
+# define my_htobe16(x) (x)
+# define my_betoh16(x) (x)
+# define my_htobe32(x) (x)
+# define my_betoh32(x) (x)
+# define my_htole16(x) _swab_16_(x)
+# define my_letoh16(x) _swab_16_(x)
+# define my_htole32(x) _swab_32_(x)
+# define my_letoh32(x) _swab_32_(x)
+# ifdef HAS_QUAD
+# define my_htobe64(x) (x)
+# define my_betoh64(x) (x)
+# define my_htole64(x) _swab_64_(x)
+# define my_letoh64(x) _swab_64_(x)
+# endif
+# define my_htobes(x) (x)
+# define my_betohs(x) (x)
+# define my_htobei(x) (x)
+# define my_betohi(x) (x)
+# define my_htobel(x) (x)
+# define my_betohl(x) (x)
+# if SHORTSIZE == 1
+# define my_htoles(x) (x)
+# define my_letohs(x) (x)
+# elif SHORTSIZE == 2
+# define my_htoles(x) _swab_16_(x)
+# define my_letohs(x) _swab_16_(x)
+# elif SHORTSIZE == 4
+# define my_htoles(x) _swab_32_(x)
+# define my_letohs(x) _swab_32_(x)
+# elif SHORTSIZE == 8
+# define my_htoles(x) _swab_64_(x)
+# define my_letohs(x) _swab_64_(x)
+# else
+# define PERL_NEED_MY_HTOLES
+# define PERL_NEED_MY_LETOHS
+# endif
+# if INTSIZE == 1
+# define my_htolei(x) (x)
+# define my_letohi(x) (x)
+# elif INTSIZE == 2
+# define my_htolei(x) _swab_16_(x)
+# define my_letohi(x) _swab_16_(x)
+# elif INTSIZE == 4
+# define my_htolei(x) _swab_32_(x)
+# define my_letohi(x) _swab_32_(x)
+# elif INTSIZE == 8
+# define my_htolei(x) _swab_64_(x)
+# define my_letohi(x) _swab_64_(x)
+# else
+# define PERL_NEED_MY_HTOLEI
+# define PERL_NEED_MY_LETOHI
+# endif
+# if LONGSIZE == 1
+# define my_htolel(x) (x)
+# define my_letohl(x) (x)
+# elif LONGSIZE == 2
+# define my_htolel(x) _swab_16_(x)
+# define my_letohl(x) _swab_16_(x)
+# elif LONGSIZE == 4
+# define my_htolel(x) _swab_32_(x)
+# define my_letohl(x) _swab_32_(x)
+# elif LONGSIZE == 8
+# define my_htolel(x) _swab_64_(x)
+# define my_letohl(x) _swab_64_(x)
+# else
+# define PERL_NEED_MY_HTOLEL
+# define PERL_NEED_MY_LETOHL
+# endif
+# define my_htolen(p,n) my_swabn(p,n)
+# define my_letohn(p,n) my_swabn(p,n)
+# define my_htoben(p,n) NOOP
+# define my_betohn(p,n) NOOP
+/*----------------------------------------------------------------------------*/
+# else /* all other byte-orders */
+/*----------------------------------------------------------------------------*/
+# define PERL_NEED_MY_HTOLE16
+# define PERL_NEED_MY_LETOH16
+# define PERL_NEED_MY_HTOBE16
+# define PERL_NEED_MY_BETOH16
+# define PERL_NEED_MY_HTOLE32
+# define PERL_NEED_MY_LETOH32
+# define PERL_NEED_MY_HTOBE32
+# define PERL_NEED_MY_BETOH32
+# ifdef HAS_QUAD
+# define PERL_NEED_MY_HTOLE64
+# define PERL_NEED_MY_LETOH64
+# define PERL_NEED_MY_HTOBE64
+# define PERL_NEED_MY_BETOH64
+# endif
+# define PERL_NEED_MY_HTOLES
+# define PERL_NEED_MY_LETOHS
+# define PERL_NEED_MY_HTOBES
+# define PERL_NEED_MY_BETOHS
+# define PERL_NEED_MY_HTOLEI
+# define PERL_NEED_MY_LETOHI
+# define PERL_NEED_MY_HTOBEI
+# define PERL_NEED_MY_BETOHI
+# define PERL_NEED_MY_HTOLEL
+# define PERL_NEED_MY_LETOHL
+# define PERL_NEED_MY_HTOBEL
+# define PERL_NEED_MY_BETOHL
+/*----------------------------------------------------------------------------*/
+# endif /* end of byte-order macros */
+/*----------------------------------------------------------------------------*/
+
+#endif /* PERL_CORE */
+
/* Cannot include embed.h here on Win32 as win32.h has not
yet been included and defines some config variables e.g. HAVE_INTERP_INTERN
*/
# endif
#endif
+#ifndef HAS_QUAD
+# undef PERL_NEED_MY_HTOLE64
+# undef PERL_NEED_MY_LETOH64
+# undef PERL_NEED_MY_HTOBE64
+# undef PERL_NEED_MY_BETOH64
+#endif
+
#if defined(uts) || defined(UTS)
# undef UV_MAX
# define UV_MAX (4294967295u)
(X) You can't allocate more than 64K on an MS-DOS machine.
-=item '!' allowed only after types %s
+=item '%c' allowed only after types %s
-(F) The '!' is allowed in pack() or unpack() only after certain types.
-See L<perlfunc/pack>.
+(F) The modifiers '!', '<' and '>' are allowed in pack() or unpack() only
+after certain types. See L<perlfunc/pack>.
=item Ambiguous call resolved as CORE::%s(), qualify as such or use &
point. For example, it'd be kind of silly to put a B<-x> on the #!
line.
+=item Can't %s %s-endian %ss on this platform
+
+(F) Your platform's byte-order is neither big-endian nor little-endian,
+or it has a very strange pointer size. Packing and unpacking big- or
+little-endian floating point values and pointers may not be possible.
+See L<perlfunc/pack>.
+
=item Can't exec "%s": %s
(W exec) A system(), exec(), or piped open call could not execute the
Errno.pm module. The Errno module is expected to tie the %! hash to
provide symbolic names for C<$!> errno values.
+=item Can't use both '<' and '>' after type '%c' in %s
+
+(F) A type cannot be forced to have both big-endian and little-endian
+byte-order at the same time, so this combination of modifiers is not
+allowed. See L<perlfunc/pack>.
+
=item Can't use %s for loop variable
(F) Only a simple scalar variable may be used as a loop variable on a
(S malloc) An internal routine called free() on something that had
already been freed.
+=item Duplicate modifier '%c' after '%c' in %s
+
+(W) You have applied the same modifier more than once after a type
+in a pack template. See L<perlfunc/pack>.
+
=item elseif should be elsif
(S syntax) There is no keyword "elseif" in Perl because Larry thinks it's
recent than the currently running version. How long has it been since
you upgraded, anyway? See L<perlfunc/require>.
+=item Perl_my_%s() not available
+
+(F) Your platform has very uncommon byte-order and integer size,
+so it was not possible to set up some or all fixed-width byte-order
+conversion functions. This is only a problem when you're using the
+'<' or '>' modifiers in (un)pack templates. See L<perlfunc/pack>.
+
=item PERL_SH_DIR too long
(F) An error peculiar to OS/2. PERL_SH_DIR is the directory to find the
h A hex string (low nybble first).
H A hex string (high nybble first).
- c A signed char value.
+ c A signed char (8-bit) value.
C An unsigned char value. Only does bytes. See U for Unicode.
- s A signed short value.
+ s A signed short (16-bit) value.
S An unsigned short value.
- (This 'short' is _exactly_ 16 bits, which may differ from
- what a local C compiler calls 'short'. If you want
- native-length shorts, use the '!' suffix.)
- i A signed integer value.
- I An unsigned integer value.
- (This 'integer' is _at_least_ 32 bits wide. Its exact
- size depends on what a local C compiler calls 'int',
- and may even be larger than the 'long' described in
- the next item.)
-
- l A signed long value.
+ l A signed long (32-bit) value.
L An unsigned long value.
- (This 'long' is _exactly_ 32 bits, which may differ from
- what a local C compiler calls 'long'. If you want
- native-length longs, use the '!' suffix.)
-
- n An unsigned short in "network" (big-endian) order.
- N An unsigned long in "network" (big-endian) order.
- v An unsigned short in "VAX" (little-endian) order.
- V An unsigned long in "VAX" (little-endian) order.
- (These 'shorts' and 'longs' are _exactly_ 16 bits and
- _exactly_ 32 bits, respectively. If you want signed
- types instead of unsigned ones, use the '!' suffix.
- Note that this is _only_ safe if signed integers are
- stored in the same format on all platforms using the
- packed data.)
q A signed quad (64-bit) value.
Q An unsigned quad value.
integer values _and_ if Perl has been compiled to support those.
Causes a fatal error otherwise.)
- j A signed integer value (a Perl internal integer, IV).
- J An unsigned integer value (a Perl internal unsigned integer, UV).
+ i A signed integer value.
+ I A unsigned integer value.
+ (This 'integer' is _at_least_ 32 bits wide. Its exact
+ size depends on what a local C compiler calls 'int'.)
+
+ n An unsigned short (16-bit) in "network" (big-endian) order.
+ N An unsigned long (32-bit) in "network" (big-endian) order.
+ v An unsigned short (16-bit) in "VAX" (little-endian) order.
+ V An unsigned long (32-bit) in "VAX" (little-endian) order.
+
+ j A Perl internal signed integer value (IV).
+ J A Perl internal unsigned integer value (UV).
f A single-precision float in the native format.
d A double-precision float in the native format.
- F A floating point value in the native native format
- (a Perl internal floating point value, NV).
+ F A Perl internal floating point value (NV) in the native format
D A long double-precision float in the native format.
(Long doubles are available only if your system supports long
double values _and_ if Perl has been compiled to support those.
the innermost ()-group.
( Start of a ()-group.
+Some letters in the TEMPLATE may optionally be followed by one or
+more of these modifiers (the second column lists the letters for
+which the modifier is valid):
+
+ ! sSlLiI Forces native (short, long, int) sizes instead
+ of fixed (16-/32-bit) sizes.
+
+ xX Make x and X act as alignment commands.
+
+ nNvV Treat integers as signed instead of unsigned.
+
+ > sSiIlLqQ Force big-endian byte-order on the type.
+ jJfFdDpP (The "big end" touches the construct.)
+
+ < sSiIlLqQ Force little-endian byte-order on the type.
+ jJfFdDpP (The "little end" touches the construct.)
+
The following rules apply:
=over 8
length. A NULL pointer is created if the corresponding value for C<p> or
C<P> is C<undef>, similarly for unpack().
+If your system has a strange pointer size (i.e. a pointer is neither as
+big as an int nor as big as a long), it may not be possible to pack or
+unpack pointers in big- or little-endian byte order. Attempting to do
+so will result in a fatal error.
+
=item *
The C</> template character allows packing and unpacking of strings where
=item *
The integer types C<s>, C<S>, C<l>, and C<L> may be
-immediately followed by a C<!> suffix to signify native shorts or
+followed by a C<!> modifier to signify native shorts or
longs--as you can see from above for example a bare C<l> does mean
exactly 32 bits, the native C<long> (as seen by the local C compiler)
may be larger. This is an issue mainly in 64-bit platforms. You can
Byteorders C<'1234'> and C<'12345678'> are little-endian, C<'4321'>
and C<'87654321'> are big-endian.
-If you want portable packed integers use the formats C<n>, C<N>,
-C<v>, and C<V>, their byte endianness and size are known.
+If you want portable packed integers you can either use the formats
+C<n>, C<N>, C<v>, and C<V>, or you can use the C<E<gt>> and C<E<lt>>
+modifiers. These modifiers are only available as of perl 5.8.5.
See also L<perlport>.
=item *
+All integer and floating point formats as well as C<p> and C<P> may
+be followed by the C<E<gt>> or C<E<lt>> modifiers to force big- or
+little- endian byte-order, respectively. This is especially useful,
+since C<n>, C<N>, C<v> and C<V> don't cover signed integers, 64-bit
+integers and floating point values. However, there are some things
+to keep in mind.
+
+Exchanging signed integers between different platforms only works
+if all platforms store them in the same format. Most platforms store
+signed integers in two's complement, so usually this is not an issue.
+
+The C<E<gt>> or C<E<lt>> modifiers can only be used on floating point
+formats on big- or little-endian machines. Otherwise, attempting to
+do so will result in a fatal error.
+
+Forcing big- or little-endian byte-order on floating point values for
+data exchange can only work if all platforms are using the same
+binary representation (e.g. IEEE floating point format). Even if all
+platforms are using IEEE, there may be subtle differences. Being able
+to use C<E<gt>> or C<E<lt>> on floating point values can be very useful,
+but also very dangerous if you don't know exactly what you're doing.
+It is definetely not a general way to portably store floating point
+values.
+
+=item *
+
Real numbers (floats and doubles) are in the native machine format only;
due to the multiplicity of floating formats around, and the lack of a
standard "network" representation, no facility for interchange has been
arithmetic (as the endian-ness of the memory representation is not part
of the IEEE spec). See also L<perlport>.
-Note that Perl uses doubles internally for all numeric calculation, and
-converting from double into float and thence back to double again will
-lose precision (i.e., C<unpack("f", pack("f", $foo)>) will not in general
-equal $foo).
+If you know exactly what you're doing, you can use the C<E<gt>> or C<E<lt>>
+modifiers to force big- or little-endian byte-order on floating point values.
+
+Note that Perl uses doubles (or long doubles, if configured) internally for
+all numeric calculation, and converting from double into float and thence back
+to double again will lose precision (i.e., C<unpack("f", pack("f", $foo)>)
+will not in general equal $foo).
=item *
A comment in a TEMPLATE starts with C<#> and goes to the end of line.
White space may be used to separate pack codes from each other, but
-a C<!> modifier and a repeat count must follow immediately.
+modifiers and a repeat count must follow immediately.
=item *
# short 12, zero fill to position 4, long 34
# $foo eq $bar
+ $foo = pack('nN', 42, 4711);
+ # pack big-endian 16- and 32-bit unsigned integers
+ $foo = pack('S>L>', 42, 4711);
+ # exactly the same
+ $foo = pack('s<l<', -42, 4711);
+ # pack little-endian 16- and 32-bit signed integers
+
The same template may generally also be used in unpack().
=item package NAMESPACE
connections use the C<pack> and C<unpack> formats C<n> and C<N>, the
"network" orders. These are guaranteed to be portable.
+As of perl 5.8.5, you can also use the C<E<gt>> and C<E<lt>> modifiers
+to force big- or little-endian byte-order. This is useful if you want
+to store signed integers or 64-bit integers, for example.
+
You can explore the endianness of your platform by unpacking a
data structure packed in native format such as:
/* CROSSCOMPILE and MULTIARCH are going to affect pp_pack() and pp_unpack().
--jhi Feb 1999 */
-#if SHORTSIZE != SIZE16 || LONGSIZE != SIZE32
-# define PERL_NATINT_PACK
-#endif
-
-#if LONGSIZE > 4 && defined(_CRAY)
-# if BYTEORDER == 0x12345678
+#if U16SIZE > SIZE16 || U32SIZE > SIZE32
+# if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678 /* little-endian */
# define OFF16(p) (char*)(p)
# define OFF32(p) (char*)(p)
# else
-# if BYTEORDER == 0x87654321
+# if BYTEORDER == 0x4321 || BYTEORDER == 0x87654321 /* big-endian */
# define OFF16(p) ((char*)(p) + (sizeof(U16) - SIZE16))
# define OFF32(p) ((char*)(p) + (sizeof(U32) - SIZE32))
# else
#endif
#define TYPE_IS_SHRIEKING 0x100
+#define TYPE_IS_BIG_ENDIAN 0x200
+#define TYPE_IS_LITTLE_ENDIAN 0x400
+#define TYPE_ENDIANNESS_MASK (TYPE_IS_BIG_ENDIAN|TYPE_IS_LITTLE_ENDIAN)
+#define TYPE_NO_ENDIANNESS(t) ((t) & ~TYPE_ENDIANNESS_MASK)
+#define TYPE_NO_MODIFIERS(t) ((t) & 0xFF)
+
+#define DO_BO_UNPACK(var, type) \
+ STMT_START { \
+ switch (datumtype & TYPE_ENDIANNESS_MASK) { \
+ case TYPE_IS_BIG_ENDIAN: var = my_betoh ## type (var); break; \
+ case TYPE_IS_LITTLE_ENDIAN: var = my_letoh ## type (var); break; \
+ default: break; \
+ } \
+ } STMT_END
+
+#define DO_BO_PACK(var, type) \
+ STMT_START { \
+ switch (datumtype & TYPE_ENDIANNESS_MASK) { \
+ case TYPE_IS_BIG_ENDIAN: var = my_htobe ## type (var); break; \
+ case TYPE_IS_LITTLE_ENDIAN: var = my_htole ## type (var); break; \
+ default: break; \
+ } \
+ } STMT_END
+
+#define DO_BO_UNPACK_PTR(var, type, pre_cast) \
+ STMT_START { \
+ switch (datumtype & TYPE_ENDIANNESS_MASK) { \
+ case TYPE_IS_BIG_ENDIAN: \
+ var = (void *) my_betoh ## type ((pre_cast) var); \
+ break; \
+ case TYPE_IS_LITTLE_ENDIAN: \
+ var = (void *) my_letoh ## type ((pre_cast) var); \
+ break; \
+ default: \
+ break; \
+ } \
+ } STMT_END
+
+#define DO_BO_PACK_PTR(var, type, pre_cast) \
+ STMT_START { \
+ switch (datumtype & TYPE_ENDIANNESS_MASK) { \
+ case TYPE_IS_BIG_ENDIAN: \
+ var = (void *) my_htobe ## type ((pre_cast) var); \
+ break; \
+ case TYPE_IS_LITTLE_ENDIAN: \
+ var = (void *) my_htole ## type ((pre_cast) var); \
+ break; \
+ default: \
+ break; \
+ } \
+ } STMT_END
+
+#define BO_CANT_DOIT(action, type) \
+ STMT_START { \
+ switch (datumtype & TYPE_ENDIANNESS_MASK) { \
+ case TYPE_IS_BIG_ENDIAN: \
+ Perl_croak(aTHX_ "Can't %s big-endian %ss on this " \
+ "platform", #action, #type); \
+ break; \
+ case TYPE_IS_LITTLE_ENDIAN: \
+ Perl_croak(aTHX_ "Can't %s little-endian %ss on this " \
+ "platform", #action, #type); \
+ break; \
+ default: \
+ break; \
+ } \
+ } STMT_END
+
+#if PTRSIZE == INTSIZE
+# define DO_BO_UNPACK_P(var) DO_BO_UNPACK_PTR(var, i, int)
+# define DO_BO_PACK_P(var) DO_BO_PACK_PTR(var, i, int)
+#elif PTRSIZE == LONGSIZE
+# define DO_BO_UNPACK_P(var) DO_BO_UNPACK_PTR(var, l, long)
+# define DO_BO_PACK_P(var) DO_BO_PACK_PTR(var, l, long)
+#else
+# define DO_BO_UNPACK_P(var) BO_CANT_DOIT(unpack, pointer)
+# define DO_BO_PACK_P(var) BO_CANT_DOIT(pack, pointer)
+#endif
+
+#if defined(my_htolen) && defined(my_letohn) && \
+ defined(my_htoben) && defined(my_betohn)
+# define DO_BO_UNPACK_N(var, type) \
+ STMT_START { \
+ switch (datumtype & TYPE_ENDIANNESS_MASK) { \
+ case TYPE_IS_BIG_ENDIAN: my_betohn(&var, sizeof(type)); break;\
+ case TYPE_IS_LITTLE_ENDIAN: my_letohn(&var, sizeof(type)); break;\
+ default: break; \
+ } \
+ } STMT_END
+
+# define DO_BO_PACK_N(var, type) \
+ STMT_START { \
+ switch (datumtype & TYPE_ENDIANNESS_MASK) { \
+ case TYPE_IS_BIG_ENDIAN: my_htoben(&var, sizeof(type)); break;\
+ case TYPE_IS_LITTLE_ENDIAN: my_htolen(&var, sizeof(type)); break;\
+ default: break; \
+ } \
+ } STMT_END
+#else
+# define DO_BO_UNPACK_N(var, type) BO_CANT_DOIT(unpack, type)
+# define DO_BO_PACK_N(var, type) BO_CANT_DOIT(pack, type)
+#endif
/* Returns the sizeof() struct described by pat */
STATIC I32
break;
}
- switch(symptr->code) {
+ /* endianness doesn't influence the size of a type */
+ switch(TYPE_NO_ENDIANNESS(symptr->code)) {
default:
- Perl_croak(aTHX_ "Invalid type '%c' in %s",
- (int)symptr->code,
+ Perl_croak(aTHX_ "Invalid type '%c' in %s",
+ (int)TYPE_NO_MODIFIERS(symptr->code),
symptr->flags & FLAG_PACK ? "pack" : "unpack" );
case '@':
case '/':
symptr->flags & FLAG_PACK ? "pack" : "unpack" );
}
- /* test for '!' modifier */
- if (patptr < patend && *patptr == '!') {
- static const char natstr[] = "sSiIlLxXnNvV";
- patptr++;
- if (strchr(natstr, code))
- code |= TYPE_IS_SHRIEKING;
- else
- Perl_croak(aTHX_ "'!' allowed only after types %s in %s",
- natstr, symptr->flags & FLAG_PACK ? "pack" : "unpack" );
+ /* look for modifiers */
+ while (patptr < patend) {
+ const char *allowed;
+ I32 modifier = 0;
+ switch (*patptr) {
+ case '!':
+ modifier = TYPE_IS_SHRIEKING;
+ allowed = "sSiIlLxXnNvV";
+ break;
+ case '>':
+ modifier = TYPE_IS_BIG_ENDIAN;
+ allowed = "sSiIlLqQjJfFdDpP";
+ break;
+ case '<':
+ modifier = TYPE_IS_LITTLE_ENDIAN;
+ allowed = "sSiIlLqQjJfFdDpP";
+ break;
+ default:
+ break;
+ }
+ if (modifier == 0)
+ break;
+ if (!strchr(allowed, TYPE_NO_MODIFIERS(code)))
+ Perl_croak(aTHX_ "'%c' allowed only after types %s in %s", *patptr,
+ allowed, symptr->flags & FLAG_PACK ? "pack" : "unpack" );
+ if ((code | modifier) == (code | TYPE_IS_BIG_ENDIAN | TYPE_IS_LITTLE_ENDIAN))
+ Perl_croak(aTHX_ "Can't use both '<' and '>' after type '%c' in %s",
+ (int) TYPE_NO_MODIFIERS(code),
+ symptr->flags & FLAG_PACK ? "pack" : "unpack" );
+ if (ckWARN(WARN_UNPACK)) {
+ if (code & modifier)
+ Perl_warner(aTHX_ packWARN(WARN_UNPACK),
+ "Duplicate modifier '%c' after '%c' in %s",
+ *patptr, (int) TYPE_NO_MODIFIERS(code),
+ symptr->flags & FLAG_PACK ? "pack" : "unpack" );
+ }
+ code |= modifier;
+ patptr++;
}
/* look for count and/or / */
howlen_t howlen;
/* These must not be in registers: */
- short ashort;
int aint;
long along;
#ifdef HAS_QUAD
redo_switch:
beyond = s >= strend;
- switch(datumtype) {
+ switch(TYPE_NO_ENDIANNESS(datumtype)) {
default:
- Perl_croak(aTHX_ "Invalid type '%c' in unpack", (int)datumtype );
+ Perl_croak(aTHX_ "Invalid type '%c' in unpack", (int)TYPE_NO_MODIFIERS(datumtype) );
case '%':
if (howlen == e_no_len)
if (checksum) {
short ashort;
while (len-- > 0) {
- COPYNN(s, &ashort, sizeof(short));
- s += sizeof(short);
- if (checksum > bits_in_uv)
- cdouble += (NV)ashort;
- else
- cuv += ashort;
-
+ COPYNN(s, &ashort, sizeof(short));
+ DO_BO_UNPACK(ashort, s);
+ s += sizeof(short);
+ if (checksum > bits_in_uv)
+ cdouble += (NV)ashort;
+ else
+ cuv += ashort;
}
}
else {
EXTEND_MORTAL(len);
while (len-- > 0) {
COPYNN(s, &ashort, sizeof(short));
+ DO_BO_UNPACK(ashort, s);
s += sizeof(short);
sv = NEWSV(38, 0);
sv_setiv(sv, (IV)ashort);
len = along;
if (checksum) {
while (len-- > 0) {
- COPY16(s, &ashort);
-#if SHORTSIZE > SIZE16
- if (ashort > 32767)
- ashort -= 65536;
+ COPY16(s, &asshort);
+ DO_BO_UNPACK(asshort, 16);
+#if U16SIZE > SIZE16
+ if (asshort > 32767)
+ asshort -= 65536;
#endif
s += SIZE16;
if (checksum > bits_in_uv)
- cdouble += (NV)ashort;
+ cdouble += (NV)asshort;
else
- cuv += ashort;
+ cuv += asshort;
}
}
else {
EXTEND_MORTAL(len);
while (len-- > 0) {
- COPY16(s, &ashort);
-#if SHORTSIZE > SIZE16
- if (ashort > 32767)
- ashort -= 65536;
+ COPY16(s, &asshort);
+ DO_BO_UNPACK(asshort, 16);
+#if U16SIZE > SIZE16
+ if (asshort > 32767)
+ asshort -= 65536;
#endif
s += SIZE16;
sv = NEWSV(38, 0);
- sv_setiv(sv, (IV)ashort);
+ sv_setiv(sv, (IV)asshort);
PUSHs(sv_2mortal(sv));
}
}
unsigned short aushort;
while (len-- > 0) {
COPYNN(s, &aushort, sizeof(unsigned short));
+ DO_BO_UNPACK(aushort, s);
s += sizeof(unsigned short);
if (checksum > bits_in_uv)
cdouble += (NV)aushort;
while (len-- > 0) {
unsigned short aushort;
COPYNN(s, &aushort, sizeof(unsigned short));
+ DO_BO_UNPACK(aushort, s);
s += sizeof(unsigned short);
sv = NEWSV(39, 0);
sv_setiv(sv, (UV)aushort);
if (checksum) {
while (len-- > 0) {
COPY16(s, &aushort);
+ DO_BO_UNPACK(aushort, 16);
s += SIZE16;
#ifdef HAS_NTOHS
if (datumtype == 'n')
EXTEND_MORTAL(len);
while (len-- > 0) {
COPY16(s, &aushort);
+ DO_BO_UNPACK(aushort, 16);
s += SIZE16;
sv = NEWSV(39, 0);
#ifdef HAS_NTOHS
if (checksum) {
while (len-- > 0) {
Copy(s, &aint, 1, int);
+ DO_BO_UNPACK(aint, i);
s += sizeof(int);
if (checksum > bits_in_uv)
cdouble += (NV)aint;
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &aint, 1, int);
+ DO_BO_UNPACK(aint, i);
s += sizeof(int);
sv = NEWSV(40, 0);
#ifdef __osf__
if (checksum) {
while (len-- > 0) {
Copy(s, &auint, 1, unsigned int);
+ DO_BO_UNPACK(auint, i);
s += sizeof(unsigned int);
if (checksum > bits_in_uv)
cdouble += (NV)auint;
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &auint, 1, unsigned int);
+ DO_BO_UNPACK(auint, i);
s += sizeof(unsigned int);
sv = NEWSV(41, 0);
#ifdef __osf__
if (checksum) {
while (len-- > 0) {
Copy(s, &aiv, 1, IV);
+#if IVSIZE == INTSIZE
+ DO_BO_UNPACK(aiv, i);
+#elif IVSIZE == LONGSIZE
+ DO_BO_UNPACK(aiv, l);
+#elif defined(HAS_QUAD) && IVSIZE == U64SIZE
+ DO_BO_UNPACK(aiv, 64);
+#endif
s += IVSIZE;
if (checksum > bits_in_uv)
cdouble += (NV)aiv;
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &aiv, 1, IV);
+#if IVSIZE == INTSIZE
+ DO_BO_UNPACK(aiv, i);
+#elif IVSIZE == LONGSIZE
+ DO_BO_UNPACK(aiv, l);
+#elif defined(HAS_QUAD) && IVSIZE == U64SIZE
+ DO_BO_UNPACK(aiv, 64);
+#endif
s += IVSIZE;
sv = NEWSV(40, 0);
sv_setiv(sv, aiv);
if (checksum) {
while (len-- > 0) {
Copy(s, &auv, 1, UV);
+#if UVSIZE == INTSIZE
+ DO_BO_UNPACK(auv, i);
+#elif UVSIZE == LONGSIZE
+ DO_BO_UNPACK(auv, l);
+#elif defined(HAS_QUAD) && UVSIZE == U64SIZE
+ DO_BO_UNPACK(auv, 64);
+#endif
s += UVSIZE;
if (checksum > bits_in_uv)
cdouble += (NV)auv;
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &auv, 1, UV);
+#if UVSIZE == INTSIZE
+ DO_BO_UNPACK(auv, i);
+#elif UVSIZE == LONGSIZE
+ DO_BO_UNPACK(auv, l);
+#elif defined(HAS_QUAD) && UVSIZE == U64SIZE
+ DO_BO_UNPACK(auv, 64);
+#endif
s += UVSIZE;
sv = NEWSV(41, 0);
sv_setuv(sv, auv);
if (checksum) {
while (len-- > 0) {
COPYNN(s, &along, sizeof(long));
+ DO_BO_UNPACK(along, l);
s += sizeof(long);
if (checksum > bits_in_uv)
cdouble += (NV)along;
EXTEND_MORTAL(len);
while (len-- > 0) {
COPYNN(s, &along, sizeof(long));
+ DO_BO_UNPACK(along, l);
s += sizeof(long);
sv = NEWSV(42, 0);
sv_setiv(sv, (IV)along);
I32 along;
#endif
COPY32(s, &along);
+ DO_BO_UNPACK(along, 32);
#if LONGSIZE > SIZE32
if (along > 2147483647)
along -= 4294967296;
I32 along;
#endif
COPY32(s, &along);
+ DO_BO_UNPACK(along, 32);
#if LONGSIZE > SIZE32
if (along > 2147483647)
along -= 4294967296;
while (len-- > 0) {
unsigned long aulong;
COPYNN(s, &aulong, sizeof(unsigned long));
+ DO_BO_UNPACK(aulong, l);
s += sizeof(unsigned long);
if (checksum > bits_in_uv)
cdouble += (NV)aulong;
while (len-- > 0) {
unsigned long aulong;
COPYNN(s, &aulong, sizeof(unsigned long));
+ DO_BO_UNPACK(aulong, l);
s += sizeof(unsigned long);
sv = NEWSV(43, 0);
sv_setuv(sv, (UV)aulong);
if (checksum) {
while (len-- > 0) {
COPY32(s, &aulong);
+ DO_BO_UNPACK(aulong, 32);
s += SIZE32;
#ifdef HAS_NTOHL
if (datumtype == 'N')
EXTEND_MORTAL(len);
while (len-- > 0) {
COPY32(s, &aulong);
+ DO_BO_UNPACK(aulong, 32);
s += SIZE32;
#ifdef HAS_NTOHL
if (datumtype == 'N')
break;
else {
Copy(s, &aptr, 1, char*);
+ DO_BO_UNPACK_P(aptr);
s += sizeof(char*);
}
sv = NEWSV(44, 0);
break;
else {
Copy(s, &aptr, 1, char*);
+ DO_BO_UNPACK_P(aptr);
s += sizeof(char*);
}
sv = NEWSV(44, 0);
if (checksum) {
while (len-- > 0) {
Copy(s, &aquad, 1, Quad_t);
+ DO_BO_UNPACK(aquad, 64);
s += sizeof(Quad_t);
if (checksum > bits_in_uv)
cdouble += (NV)aquad;
aquad = 0;
else {
Copy(s, &aquad, 1, Quad_t);
+ DO_BO_UNPACK(aquad, 64);
s += sizeof(Quad_t);
}
sv = NEWSV(42, 0);
if (checksum) {
while (len-- > 0) {
Copy(s, &auquad, 1, Uquad_t);
+ DO_BO_UNPACK(auquad, 64);
s += sizeof(Uquad_t);
if (checksum > bits_in_uv)
cdouble += (NV)auquad;
auquad = 0;
else {
Copy(s, &auquad, 1, Uquad_t);
+ DO_BO_UNPACK(auquad, 64);
s += sizeof(Uquad_t);
}
sv = NEWSV(43, 0);
if (checksum) {
while (len-- > 0) {
Copy(s, &afloat, 1, float);
+ DO_BO_UNPACK_N(afloat, float);
s += sizeof(float);
cdouble += afloat;
}
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &afloat, 1, float);
+ DO_BO_UNPACK_N(afloat, float);
s += sizeof(float);
sv = NEWSV(47, 0);
sv_setnv(sv, (NV)afloat);
if (checksum) {
while (len-- > 0) {
Copy(s, &adouble, 1, double);
+ DO_BO_UNPACK_N(adouble, double);
s += sizeof(double);
cdouble += adouble;
}
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &adouble, 1, double);
+ DO_BO_UNPACK_N(adouble, double);
s += sizeof(double);
sv = NEWSV(48, 0);
sv_setnv(sv, (NV)adouble);
if (checksum) {
while (len-- > 0) {
Copy(s, &anv, 1, NV);
+ DO_BO_UNPACK_N(anv, NV);
s += NVSIZE;
cdouble += anv;
}
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &anv, 1, NV);
+ DO_BO_UNPACK_N(anv, NV);
s += NVSIZE;
sv = NEWSV(48, 0);
sv_setnv(sv, anv);
if (checksum) {
while (len-- > 0) {
Copy(s, &aldouble, 1, long double);
+ DO_BO_UNPACK_N(aldouble, long double);
s += LONG_DOUBLESIZE;
cdouble += aldouble;
}
EXTEND_MORTAL(len);
while (len-- > 0) {
Copy(s, &aldouble, 1, long double);
+ DO_BO_UNPACK_N(aldouble, long double);
s += LONG_DOUBLESIZE;
sv = NEWSV(48, 0);
sv_setnv(sv, (NV)aldouble);
if (checksum) {
sv = NEWSV(42, 0);
- if (strchr("fFdD", datumtype) ||
+ if (strchr("fFdD", TYPE_NO_MODIFIERS(datumtype)) ||
(checksum > bits_in_uv &&
- strchr("csSiIlLnNUvVqQjJ", datumtype&0xFF)) ) {
+ strchr("csSiIlLnNUvVqQjJ", TYPE_NO_MODIFIERS(datumtype))) ) {
NV trouble;
adouble = (NV) (1 << (checksum & 15));
len = symptr->length;
break;
case e_star:
- len = strchr("@Xxu", datumtype) ? 0 : items;
+ len = strchr("@Xxu", TYPE_NO_MODIFIERS(datumtype)) ? 0 : items;
break;
}
}
}
- switch(datumtype) {
+ switch(TYPE_NO_ENDIANNESS(datumtype)) {
default:
- Perl_croak(aTHX_ "Invalid type '%c' in pack", (int)datumtype);
+ Perl_croak(aTHX_ "Invalid type '%c' in pack", (int)TYPE_NO_MODIFIERS(datumtype));
case '%':
Perl_croak(aTHX_ "'%%' may not be used in pack");
case '@':
case 'c':
while (len-- > 0) {
fromstr = NEXTFROM;
- switch (datumtype) {
+ switch (TYPE_NO_MODIFIERS(datumtype)) {
case 'C':
aint = SvIV(fromstr);
if ((aint < 0 || aint > 255) &&
afloat = (float)SvNV(fromstr);
# endif
#endif
+ DO_BO_PACK_N(afloat, float);
sv_catpvn(cat, (char *)&afloat, sizeof (float));
}
break;
adouble = (double)SvNV(fromstr);
# endif
#endif
+ DO_BO_PACK_N(adouble, double);
sv_catpvn(cat, (char *)&adouble, sizeof (double));
}
break;
case 'F':
+ Zero(&anv, 1, NV); /* can be long double with unused bits */
while (len-- > 0) {
fromstr = NEXTFROM;
anv = SvNV(fromstr);
+ DO_BO_PACK_N(anv, NV);
sv_catpvn(cat, (char *)&anv, NVSIZE);
}
break;
#if defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE)
case 'D':
+ /* long doubles can have unused bits, which may be nonzero */
+ Zero(&aldouble, 1, long double);
while (len-- > 0) {
fromstr = NEXTFROM;
aldouble = (long double)SvNV(fromstr);
+ DO_BO_PACK_N(aldouble, long double);
sv_catpvn(cat, (char *)&aldouble, LONG_DOUBLESIZE);
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
aushort = SvUV(fromstr);
+ DO_BO_PACK(aushort, s);
sv_catpvn(cat, (char *)&aushort, sizeof(unsigned short));
}
}
while (len-- > 0) {
fromstr = NEXTFROM;
aushort = (U16)SvUV(fromstr);
+ DO_BO_PACK(aushort, 16);
CAT16(cat, &aushort);
}
while (len-- > 0) {
fromstr = NEXTFROM;
ashort = SvIV(fromstr);
+ DO_BO_PACK(ashort, s);
sv_catpvn(cat, (char *)&ashort, sizeof(short));
}
}
while (len-- > 0) {
fromstr = NEXTFROM;
ashort = (I16)SvIV(fromstr);
+ DO_BO_PACK(ashort, 16);
CAT16(cat, &ashort);
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
auint = SvUV(fromstr);
+ DO_BO_PACK(auint, i);
sv_catpvn(cat, (char*)&auint, sizeof(unsigned int));
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
aiv = SvIV(fromstr);
+#if IVSIZE == INTSIZE
+ DO_BO_PACK(aiv, i);
+#elif IVSIZE == LONGSIZE
+ DO_BO_PACK(aiv, l);
+#elif defined(HAS_QUAD) && IVSIZE == U64SIZE
+ DO_BO_PACK(aiv, 64);
+#endif
sv_catpvn(cat, (char*)&aiv, IVSIZE);
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
auv = SvUV(fromstr);
+#if UVSIZE == INTSIZE
+ DO_BO_PACK(auv, i);
+#elif UVSIZE == LONGSIZE
+ DO_BO_PACK(auv, l);
+#elif defined(HAS_QUAD) && UVSIZE == U64SIZE
+ DO_BO_PACK(auv, 64);
+#endif
sv_catpvn(cat, (char*)&auv, UVSIZE);
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
aint = SvIV(fromstr);
+ DO_BO_PACK(aint, i);
sv_catpvn(cat, (char*)&aint, sizeof(int));
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
aulong = SvUV(fromstr);
+ DO_BO_PACK(aulong, l);
sv_catpvn(cat, (char *)&aulong, sizeof(unsigned long));
}
}
while (len-- > 0) {
fromstr = NEXTFROM;
aulong = SvUV(fromstr);
+ DO_BO_PACK(aulong, 32);
CAT32(cat, &aulong);
}
}
while (len-- > 0) {
fromstr = NEXTFROM;
along = SvIV(fromstr);
+ DO_BO_PACK(along, l);
sv_catpvn(cat, (char *)&along, sizeof(long));
}
}
while (len-- > 0) {
fromstr = NEXTFROM;
along = SvIV(fromstr);
+ DO_BO_PACK(along, 32);
CAT32(cat, &along);
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
auquad = (Uquad_t)SvUV(fromstr);
+ DO_BO_PACK(auquad, 64);
sv_catpvn(cat, (char*)&auquad, sizeof(Uquad_t));
}
break;
while (len-- > 0) {
fromstr = NEXTFROM;
aquad = (Quad_t)SvIV(fromstr);
+ DO_BO_PACK(aquad, 64);
sv_catpvn(cat, (char*)&aquad, sizeof(Quad_t));
}
break;
else
aptr = SvPV_force(fromstr,n_a);
}
+ DO_BO_PACK_P(aptr);
sv_catpvn(cat, (char*)&aptr, sizeof(char*));
}
break;
PERL_CALLCONV SV* Perl_hv_scalar(pTHX_ HV* hv);
PERL_CALLCONV SV* Perl_magic_scalarpack(pTHX_ HV* hv, MAGIC* mg);
+#ifdef PERL_NEED_MY_HTOLE16
+PERL_CALLCONV U16 Perl_my_htole16(U16 n);
+#endif
+#ifdef PERL_NEED_MY_LETOH16
+PERL_CALLCONV U16 Perl_my_letoh16(U16 n);
+#endif
+#ifdef PERL_NEED_MY_HTOBE16
+PERL_CALLCONV U16 Perl_my_htobe16(U16 n);
+#endif
+#ifdef PERL_NEED_MY_BETOH16
+PERL_CALLCONV U16 Perl_my_betoh16(U16 n);
+#endif
+#ifdef PERL_NEED_MY_HTOLE32
+PERL_CALLCONV U32 Perl_my_htole32(U32 n);
+#endif
+#ifdef PERL_NEED_MY_LETOH32
+PERL_CALLCONV U32 Perl_my_letoh32(U32 n);
+#endif
+#ifdef PERL_NEED_MY_HTOBE32
+PERL_CALLCONV U32 Perl_my_htobe32(U32 n);
+#endif
+#ifdef PERL_NEED_MY_BETOH32
+PERL_CALLCONV U32 Perl_my_betoh32(U32 n);
+#endif
+#ifdef PERL_NEED_MY_HTOLE64
+PERL_CALLCONV U64 Perl_my_htole64(U64 n);
+#endif
+#ifdef PERL_NEED_MY_LETOH64
+PERL_CALLCONV U64 Perl_my_letoh64(U64 n);
+#endif
+#ifdef PERL_NEED_MY_HTOBE64
+PERL_CALLCONV U64 Perl_my_htobe64(U64 n);
+#endif
+#ifdef PERL_NEED_MY_BETOH64
+PERL_CALLCONV U64 Perl_my_betoh64(U64 n);
+#endif
+
+#ifdef PERL_NEED_MY_HTOLES
+PERL_CALLCONV short Perl_my_htoles(short n);
+#endif
+#ifdef PERL_NEED_MY_LETOHS
+PERL_CALLCONV short Perl_my_letohs(short n);
+#endif
+#ifdef PERL_NEED_MY_HTOBES
+PERL_CALLCONV short Perl_my_htobes(short n);
+#endif
+#ifdef PERL_NEED_MY_BETOHS
+PERL_CALLCONV short Perl_my_betohs(short n);
+#endif
+#ifdef PERL_NEED_MY_HTOLEI
+PERL_CALLCONV int Perl_my_htolei(int n);
+#endif
+#ifdef PERL_NEED_MY_LETOHI
+PERL_CALLCONV int Perl_my_letohi(int n);
+#endif
+#ifdef PERL_NEED_MY_HTOBEI
+PERL_CALLCONV int Perl_my_htobei(int n);
+#endif
+#ifdef PERL_NEED_MY_BETOHI
+PERL_CALLCONV int Perl_my_betohi(int n);
+#endif
+#ifdef PERL_NEED_MY_HTOLEL
+PERL_CALLCONV long Perl_my_htolel(long n);
+#endif
+#ifdef PERL_NEED_MY_LETOHL
+PERL_CALLCONV long Perl_my_letohl(long n);
+#endif
+#ifdef PERL_NEED_MY_HTOBEL
+PERL_CALLCONV long Perl_my_htobel(long n);
+#endif
+#ifdef PERL_NEED_MY_BETOHL
+PERL_CALLCONV long Perl_my_betohl(long n);
+#endif
+
+PERL_CALLCONV void Perl_my_swabn(void* ptr, int n);
+
END_EXTERN_C
require './test.pl';
}
-plan tests => 6076;
+plan tests => 13576;
use strict;
use warnings;
my $Is_EBCDIC = (defined $Config{ebcdic} && $Config{ebcdic} eq 'define');
my $Perl = which_perl();
+my @valid_errors = (qr/^Invalid type '\w'/);
+
+my $ByteOrder = 'unknown';
+my $maybe_not_avail = '(?:hto[bl]e|[bl]etoh)';
+if ($Config{byteorder} =~ /^1234(?:5678)?$/) {
+ $ByteOrder = 'little';
+ $maybe_not_avail = '(?:htobe|betoh)';
+}
+elsif ($Config{byteorder} =~ /^(?:8765)?4321$/) {
+ $ByteOrder = 'big';
+ $maybe_not_avail = '(?:htole|letoh)';
+}
+else {
+ push @valid_errors, qr/^Can't (?:un)?pack (?:big|little)-endian .*? on this platform/;
+}
+
+for my $size ( 16, 32, 64 ) {
+ if (exists $Config{"u${size}size"} and $Config{"u${size}size"} != ($size >> 3)) {
+ push @valid_errors, qr/^Perl_my_$maybe_not_avail$size\(\) not available/;
+ }
+}
+
+my $IsTwosComplement = pack('i', -1) eq "\xFF" x $Config{intsize};
+print "# \$IsTwosComplement = $IsTwosComplement\n";
+
+sub is_valid_error
+{
+ my $err = shift;
+
+ for my $e (@valid_errors) {
+ $err =~ $e and return 1;
+ }
+
+ return 0;
+}
sub encode_list {
my @result = map {_qq($_)} @_;
eval { $x = pack 'w', '1'x(1 + length ~0) . 'e0' };
like ($@, qr/^Can only compress unsigned integers/);
+ for my $mod (qw( ! < > )) {
+ eval { $x = pack "a$mod", 42 };
+ like ($@, qr/^'$mod' allowed only after types \w+ in pack/);
+
+ eval { $x = unpack "a$mod", 'x'x8 };
+ like ($@, qr/^'$mod' allowed only after types \w+ in unpack/);
+ }
+
+ for my $mod (qw( <> >< !<> !>< <!> >!< <>! ><! )) {
+ eval { $x = pack "sI${mod}s", 42, 47, 11 };
+ like ($@, qr/^Can't use both '<' and '>' after type 'I' in pack/);
+
+ eval { $x = unpack "sI${mod}s", 'x'x16 };
+ like ($@, qr/^Can't use both '<' and '>' after type 'I' in unpack/);
+ }
+
SKIP: {
# Is this a stupid thing to do on VMS, VOS and other unusual platforms?
($^O =~ /^svr4/ && -f "/etc/issue" && -f "/etc/.relid") # NCR MP-RAS
);
- my $inf = eval '2**10000';
+ my $inf = eval '2**1000000';
skip("Couldn't generate infinity - got error '$@'", 1)
unless defined $inf and $inf == $inf / 2 and $inf + 1 == $inf;
# I'm getting about 1e-16 on FreeBSD
my $quotient = int (100 * ($y - $big) / $big);
ok($quotient < 2 && $quotient > -2,
- "Round trip pack, unpack 'w' of $big is withing 1% ($quotient%)");
+ "Round trip pack, unpack 'w' of $big is within 1% ($quotient%)");
}
}
# literals
is(unpack("p",pack("p","foo")), "foo");
+is(unpack("p<",pack("p<","foo")), "foo");
+is(unpack("p>",pack("p>","foo")), "foo");
# scalars
is(unpack("p",pack("p",239)), 239);
+is(unpack("p<",pack("p<",239)), 239);
+is(unpack("p>",pack("p>",239)), 239);
# temps
sub foo { my $a = "a"; return $a . $a++ . $a++ }
}
# undef should give null pointer
-like(pack("p", undef), qr/^\0+/);
+like(pack("p", undef), qr/^\0+$/);
+like(pack("p<", undef), qr/^\0+$/);
+like(pack("p>", undef), qr/^\0+$/);
# Check for optimizer bug (e.g. Digital Unix GEM cc with -O4 on DU V4.0B gives
# 4294967295 instead of -1)
# see #ifdef __osf__ in pp.c pp_unpack
is((unpack("i",pack("i",-1))), -1);
-print "# test the pack lengths of s S i I l L n N v V\n";
-
-my @lengths = qw(s 2 S 2 i -4 I -4 l 4 L 4 n 2 N 4 v 2 V 4);
-while (my ($format, $expect) = splice @lengths, 0, 2) {
- my $len = length(pack($format, 0));
- if ($expect > 0) {
- is($expect, $len, "format '$format'");
- } else {
- $expect = -$expect;
- ok ($len >= $expect, "format '$format'") ||
- print "# format '$format' has length $len, expected >= $expect\n";
+print "# test the pack lengths of s S i I l L n N v V + modifiers\n";
+
+my @lengths = (
+ qw(s 2 S 2 i -4 I -4 l 4 L 4 n 2 N 4 v 2 V 4 n! 2 N! 4 v! 2 V! 4),
+ 's!' => $Config{shortsize}, 'S!' => $Config{shortsize},
+ 'i!' => $Config{intsize}, 'I!' => $Config{intsize},
+ 'l!' => $Config{longsize}, 'L!' => $Config{longsize},
+);
+
+while (my ($base, $expect) = splice @lengths, 0, 2) {
+ my @formats = ($base);
+ $base =~ /^[nv]/i or push @formats, "$base>", "$base<";
+ for my $format (@formats) {
+ my $len = length(pack($format, 0));
+ if ($expect > 0) {
+ is($expect, $len, "format '$format'");
+ } else {
+ $expect = -$expect;
+ ok ($len >= $expect, "format '$format'") ||
+ print "# format '$format' has length $len, expected >= $expect\n";
+ }
}
}
my @templates = qw(c C i I s S l L n N v V f d q Q);
-foreach my $t (@templates) {
- SKIP: {
- my @t = eval { unpack("$t*", pack("$t*", 12, 34)) };
-
- # quads not supported everywhere
- skip "Quads not supported", 4 if $@ =~ /Invalid type/;
- is( $@, '' );
+foreach my $base (@templates) {
+ my @tmpl = ($base);
+ $base =~ /^[cnv]/i or push @tmpl, "$base>", "$base<";
+ foreach my $t (@tmpl) {
+ SKIP: {
+ my @t = eval { unpack("$t*", pack("$t*", 12, 34)) };
- is(scalar @t, 2);
+ skip "cannot pack '$t' on this perl", 4
+ if is_valid_error($@);
- SKIP: {
- skip "$t not expected to work for some reason", 2 if $t =~ /[nv]/i;
+ is( $@, '' );
+ is(scalar @t, 2);
is($t[0], 12);
is($t[1], 34);
is(length(pack("i!", 0)), length(pack("i", 0)));
sub numbers {
- my $format = shift;
- return numbers_with_total ($format, undef, @_);
+ my $base = shift;
+ my @formats = ($base);
+ $base =~ /^[silqjfdp]/i and push @formats, "$base>", "$base<";
+ for my $format (@formats) {
+ numbers_with_total ($format, undef, @_);
+ }
}
sub numbers_with_total {
foreach (@_) {
SKIP: {
my $out = eval {unpack($format, pack($format, $_))};
- skip "cannot pack '$format' on this perl", 2 if
- $@ =~ /Invalid type '$format'/;
+ skip "cannot pack '$format' on this perl", 2
+ if is_valid_error($@);
is($@, '');
is($out, $_);
SKIP: {
my $sum = eval {unpack "%$_$format*", pack "$format*", @_};
skip "cannot pack '$format' on this perl", 3
- if $@ =~ /Invalid type '$format'/;
+ if is_valid_error($@);
is($@, '');
ok(defined $sum);
is(pack("N!", 0xdeadbeef), "\xde\xad\xbe\xef");
is(pack("V!", 0xdeadbeef), "\xef\xbe\xad\xde");
+print "# test big-/little-endian conversion\n";
+
+sub byteorder
+{
+ my $format = shift;
+ print "# byteorder test for $format\n";
+ for my $value (@_) {
+ SKIP: {
+ my($nat,$be,$le) = eval { map { pack $format.$_, $value } '', '>', '<' };
+ skip "cannot pack '$format' on this perl", 5
+ if is_valid_error($@);
+
+ print "# [$value][$nat][$be][$le][$@]\n";
+
+ SKIP: {
+ skip "cannot compare native byteorder with big-/little-endian", 1
+ if $ByteOrder eq 'unknown';
+
+ is($nat, $ByteOrder eq 'big' ? $be : $le);
+ }
+ is($be, reverse($le));
+ my @x = eval { unpack "$format$format>$format<", $nat.$be.$le };
+
+ print "# [$value][", join('][', @x), "][$@]\n";
+
+ is($@, '');
+ is($x[0], $x[1]);
+ is($x[0], $x[2]);
+ }
+ }
+}
+
+byteorder('s', -32768, -1, 0, 1, 32767);
+byteorder('S', 0, 1, 32767, 32768, 65535);
+byteorder('i', -2147483648, -1, 0, 1, 2147483647);
+byteorder('I', 0, 1, 2147483647, 2147483648, 4294967295);
+byteorder('l', -2147483648, -1, 0, 1, 2147483647);
+byteorder('L', 0, 1, 2147483647, 2147483648, 4294967295);
+byteorder('j', -2147483648, -1, 0, 1, 2147483647);
+byteorder('J', 0, 1, 2147483647, 2147483648, 4294967295);
+byteorder('s!', -32768, -1, 0, 1, 32767);
+byteorder('S!', 0, 1, 32767, 32768, 65535);
+byteorder('i!', -2147483648, -1, 0, 1, 2147483647);
+byteorder('I!', 0, 1, 2147483647, 2147483648, 4294967295);
+byteorder('l!', -2147483648, -1, 0, 1, 2147483647);
+byteorder('L!', 0, 1, 2147483647, 2147483648, 4294967295);
+byteorder('q', -9223372036854775808, -1, 0, 1, 9223372036854775807);
+byteorder('Q', 0, 1, 9223372036854775807, 9223372036854775808, 18446744073709551615);
+byteorder('f', -1, 0, 0.5, 42, 2**34);
+byteorder('F', -1, 0, 0.5, 42, 2**34);
+byteorder('d', -(2**34), -1, 0, 1, 2**34);
+byteorder('D', -(2**34), -1, 0, 1, 2**34);
+
+print "# test negative numbers\n";
+
+SKIP: {
+ skip "platform is not using two's complement for negative integers", 120
+ unless $IsTwosComplement;
+
+ for my $format (qw(s i l j s! i! l! q)) {
+ SKIP: {
+ my($nat,$be,$le) = eval { map { pack $format.$_, -1 } '', '>', '<' };
+ skip "cannot pack '$format' on this perl", 15
+ if is_valid_error($@);
+
+ my $len = length $nat;
+ is($_, "\xFF"x$len) for $nat, $be, $le;
+
+ my(@val,@ref);
+ if ($len >= 8) {
+ @val = (-2, -81985529216486896, -9223372036854775808);
+ @ref = ("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE",
+ "\xFE\xDC\xBA\x98\x76\x54\x32\x10",
+ "\x80\x00\x00\x00\x00\x00\x00\x00");
+ }
+ elsif ($len >= 4) {
+ @val = (-2, -19088744, -2147483648);
+ @ref = ("\xFF\xFF\xFF\xFE",
+ "\xFE\xDC\xBA\x98",
+ "\x80\x00\x00\x00");
+ }
+ else {
+ @val = (-2, -292, -32768);
+ @ref = ("\xFF\xFE",
+ "\xFE\xDC",
+ "\x80\x00");
+ }
+ for my $x (@ref) {
+ if ($len > length $x) {
+ $x = $x . "\xFF" x ($len - length $x);
+ }
+ }
+
+ for my $i (0 .. $#val) {
+ my($nat,$be,$le) = eval { map { pack $format.$_, $val[$i] } '', '>', '<' };
+ is($@, '');
+
+ SKIP: {
+ skip "cannot compare native byteorder with big-/little-endian", 1
+ if $ByteOrder eq 'unknown';
+
+ is($nat, $ByteOrder eq 'big' ? $be : $le);
+ }
+
+ is($be, $ref[$i]);
+ is($be, reverse($le));
+ }
+ }
+ }
+}
+
{
# /
{
local $SIG{__WARN__} = sub { $@ = "@_" };
my @null = unpack('U0U', chr(255));
- like($@, /^Malformed UTF-8 character /);
+ like($@, qr/^Malformed UTF-8 character /);
}
}
eval { my @a = unpack( "C/", "\3" ); };
like( $@, qr{Code missing after '/'} );
+ # modifier warnings
+ @warning = ();
+ $x = pack "I>>s!!", 47, 11;
+ ($x) = unpack "I<<l!>!>", 'x'x20;
+ is(scalar @warning, 5);
+ like($warning[0], qr/Duplicate modifier '>' after 'I' in pack/);
+ like($warning[1], qr/Duplicate modifier '!' after 's' in pack/);
+ like($warning[2], qr/Duplicate modifier '<' after 'I' in unpack/);
+ like($warning[3], qr/Duplicate modifier '!' after 'l' in unpack/);
+ like($warning[4], qr/Duplicate modifier '>' after 'l' in unpack/);
}
{ # Repeat count [SUBEXPR]
if (eval { pack 'q', 1 } ) {
push @codes, qw(q Q);
} else {
- push @codes, qw(c C); # Keep the count the same
+ push @codes, qw(s S); # Keep the count the same
}
if (eval { pack 'D', 1 } ) {
push @codes, 'D';
push @codes, 'd'; # Keep the count the same
}
+ push @codes, map { /^[silqjfdp]/i ? ("$_<", "$_>") : () } @codes;
+
my %val;
@val{@codes} = map { / [Xx] (?{ undef })
| [AZa] (?{ 'something' })
$c = $1 if $groupend =~ /(\d+)/;
my @list2 = (@list1) x $c;
- my $junk1 = "$groupbegin $type$count $groupend";
- # print "# junk1=$junk1\n";
- my $p = pack $junk1, @list2;
- my $half = int( (length $p)/2 );
- for my $move ('', "X$half", "X!$half", 'x1', 'x!8', "x$half") {
- my $junk = "$junk1 $move";
- # print "# junk='$junk', list=(@list2)\n";
- $p = pack "$junk $end", @list2, @end;
- my @l = unpack "x[$junk] $end", $p;
- is(scalar @l, scalar @end);
- is("@l", "@end", "skipping x[$junk]");
- }
+ SKIP: {
+ my $junk1 = "$groupbegin $type$count $groupend";
+ # print "# junk1=$junk1\n";
+ my $p = eval { pack $junk1, @list2 };
+ skip "cannot pack '$type' on this perl", 12
+ if is_valid_error($@);
+
+ my $half = int( (length $p)/2 );
+ for my $move ('', "X$half", "X!$half", 'x1', 'x!8', "x$half") {
+ my $junk = "$junk1 $move";
+ # print "# junk='$junk', list=(@list2)\n";
+ $p = pack "$junk $end", @list2, @end;
+ my @l = unpack "x[$junk] $end", $p;
+ is(scalar @l, scalar @end);
+ is("@l", "@end", "skipping x[$junk]");
+ }
+ }
}
}
}
SKIP: {
my $t = eval { unpack("D*", pack("D", 12.34)) };
- skip "Long doubles not in use", 56 if $@ =~ /Invalid type/;
+ skip "Long doubles not in use", 166 if $@ =~ /Invalid type/;
is(length(pack("D", 0)), $Config{longdblsize});
numbers ('D', -(2**34), -1, 0, 1, 2**34);
* -DWS
*/
-#define HTOV(name,type) \
+#define HTOLE(name,type) \
type \
name (register type n) \
{ \
char c[sizeof(type)]; \
} u; \
register I32 i; \
- register I32 s; \
- for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
+ register I32 s = 0; \
+ for (i = 0; i < sizeof(u.c); i++, s += 8) { \
u.c[i] = (n >> s) & 0xFF; \
} \
return u.value; \
}
-#define VTOH(name,type) \
+#define LETOH(name,type) \
type \
name (register type n) \
{ \
char c[sizeof(type)]; \
} u; \
register I32 i; \
- register I32 s; \
+ register I32 s = 0; \
u.value = n; \
n = 0; \
- for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) { \
- n += (u.c[i] & 0xFF) << s; \
+ for (i = 0; i < sizeof(u.c); i++, s += 8) { \
+ n |= ((type)(u.c[i] & 0xFF)) << s; \
} \
return n; \
}
+/*
+ * Big-endian byte order functions.
+ */
+
+#define HTOBE(name,type) \
+ type \
+ name (register type n) \
+ { \
+ union { \
+ type value; \
+ char c[sizeof(type)]; \
+ } u; \
+ register I32 i; \
+ register I32 s = 8*(sizeof(u.c)-1); \
+ for (i = 0; i < sizeof(u.c); i++, s -= 8) { \
+ u.c[i] = (n >> s) & 0xFF; \
+ } \
+ return u.value; \
+ }
+
+#define BETOH(name,type) \
+ type \
+ name (register type n) \
+ { \
+ union { \
+ type value; \
+ char c[sizeof(type)]; \
+ } u; \
+ register I32 i; \
+ register I32 s = 8*(sizeof(u.c)-1); \
+ u.value = n; \
+ n = 0; \
+ for (i = 0; i < sizeof(u.c); i++, s -= 8) { \
+ n |= ((type)(u.c[i] & 0xFF)) << s; \
+ } \
+ return n; \
+ }
+
+/*
+ * If we just can't do it...
+ */
+
+#define NOT_AVAIL(name,type) \
+ type \
+ name (register type n) \
+ { \
+ Perl_croak_nocontext(#name "() not available"); \
+ return n; /* not reached */ \
+ }
+
+
#if defined(HAS_HTOVS) && !defined(htovs)
-HTOV(htovs,short)
+HTOLE(htovs,short)
#endif
#if defined(HAS_HTOVL) && !defined(htovl)
-HTOV(htovl,long)
+HTOLE(htovl,long)
#endif
#if defined(HAS_VTOHS) && !defined(vtohs)
-VTOH(vtohs,short)
+LETOH(vtohs,short)
#endif
#if defined(HAS_VTOHL) && !defined(vtohl)
-VTOH(vtohl,long)
+LETOH(vtohl,long)
+#endif
+
+#ifdef PERL_NEED_MY_HTOLE16
+# if U16SIZE == 2
+HTOLE(Perl_my_htole16,U16)
+# else
+NOT_AVAIL(Perl_my_htole16,U16)
+# endif
+#endif
+#ifdef PERL_NEED_MY_LETOH16
+# if U16SIZE == 2
+LETOH(Perl_my_letoh16,U16)
+# else
+NOT_AVAIL(Perl_my_letoh16,U16)
+# endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE16
+# if U16SIZE == 2
+HTOBE(Perl_my_htobe16,U16)
+# else
+NOT_AVAIL(Perl_my_htobe16,U16)
+# endif
+#endif
+#ifdef PERL_NEED_MY_BETOH16
+# if U16SIZE == 2
+BETOH(Perl_my_betoh16,U16)
+# else
+NOT_AVAIL(Perl_my_betoh16,U16)
+# endif
+#endif
+
+#ifdef PERL_NEED_MY_HTOLE32
+# if U32SIZE == 4
+HTOLE(Perl_my_htole32,U32)
+# else
+NOT_AVAIL(Perl_my_htole32,U32)
+# endif
+#endif
+#ifdef PERL_NEED_MY_LETOH32
+# if U32SIZE == 4
+LETOH(Perl_my_letoh32,U32)
+# else
+NOT_AVAIL(Perl_my_letoh32,U32)
+# endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE32
+# if U32SIZE == 4
+HTOBE(Perl_my_htobe32,U32)
+# else
+NOT_AVAIL(Perl_my_htobe32,U32)
+# endif
+#endif
+#ifdef PERL_NEED_MY_BETOH32
+# if U32SIZE == 4
+BETOH(Perl_my_betoh32,U32)
+# else
+NOT_AVAIL(Perl_my_betoh32,U32)
+# endif
+#endif
+
+#ifdef PERL_NEED_MY_HTOLE64
+# if U64SIZE == 8
+HTOLE(Perl_my_htole64,U64)
+# else
+NOT_AVAIL(Perl_my_htole64,U64)
+# endif
+#endif
+#ifdef PERL_NEED_MY_LETOH64
+# if U64SIZE == 8
+LETOH(Perl_my_letoh64,U64)
+# else
+NOT_AVAIL(Perl_my_letoh64,U64)
+# endif
+#endif
+#ifdef PERL_NEED_MY_HTOBE64
+# if U64SIZE == 8
+HTOBE(Perl_my_htobe64,U64)
+# else
+NOT_AVAIL(Perl_my_htobe64,U64)
+# endif
#endif
+#ifdef PERL_NEED_MY_BETOH64
+# if U64SIZE == 8
+BETOH(Perl_my_betoh64,U64)
+# else
+NOT_AVAIL(Perl_my_betoh64,U64)
+# endif
+#endif
+
+#ifdef PERL_NEED_MY_HTOLES
+HTOLE(Perl_my_htoles,short)
+#endif
+#ifdef PERL_NEED_MY_LETOHS
+LETOH(Perl_my_letohs,short)
+#endif
+#ifdef PERL_NEED_MY_HTOBES
+HTOBE(Perl_my_htobes,short)
+#endif
+#ifdef PERL_NEED_MY_BETOHS
+BETOH(Perl_my_betohs,short)
+#endif
+
+#ifdef PERL_NEED_MY_HTOLEI
+HTOLE(Perl_my_htolei,int)
+#endif
+#ifdef PERL_NEED_MY_LETOHI
+LETOH(Perl_my_letohi,int)
+#endif
+#ifdef PERL_NEED_MY_HTOBEI
+HTOBE(Perl_my_htobei,int)
+#endif
+#ifdef PERL_NEED_MY_BETOHI
+BETOH(Perl_my_betohi,int)
+#endif
+
+#ifdef PERL_NEED_MY_HTOLEL
+HTOLE(Perl_my_htolel,long)
+#endif
+#ifdef PERL_NEED_MY_LETOHL
+LETOH(Perl_my_letohl,long)
+#endif
+#ifdef PERL_NEED_MY_HTOBEL
+HTOBE(Perl_my_htobel,long)
+#endif
+#ifdef PERL_NEED_MY_BETOHL
+BETOH(Perl_my_betohl,long)
+#endif
+
+void
+Perl_my_swabn(void *ptr, int n)
+{
+ register char *s = (char *)ptr;
+ register char *e = s + (n-1);
+ register char tc;
+
+ for (n /= 2; n > 0; s++, e--, n--) {
+ tc = *s;
+ *s = *e;
+ *e = tc;
+ }
+}
PerlIO *
Perl_my_popen_list(pTHX_ char *mode, int n, SV **args)