From e53e5edab2dd2e38d50577e6b6c5fba0dadd064a Mon Sep 17 00:00:00 2001 From: akr Date: Wed, 24 Feb 2010 15:32:06 +0000 Subject: * pack.c (pack_unpack): don't use OFF32 for gcc 4.5. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@26753 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4 + pack.c | 375 ++++++++++++++++++++++++++++++++----------------- test/ruby/test_pack.rb | 2 +- 3 files changed, 254 insertions(+), 127 deletions(-) diff --git a/ChangeLog b/ChangeLog index ced5023e7c..c28793a018 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Thu Feb 25 00:29:55 2010 Tanaka Akira + + * pack.c (pack_unpack): don't use OFF32 for gcc 4.5. + Wed Feb 24 22:39:15 2010 Tanaka Akira * lib/resolv.rb: fix [ruby-core:28320] reported by Paul Clegg. diff --git a/pack.c b/pack.c index cec5e46b9f..958a2401ac 100644 --- a/pack.c +++ b/pack.c @@ -22,6 +22,12 @@ # define NATINT_PACK #endif +#ifdef WORDS_BIGENDIAN +# define BIGENDIAN_P 1 +#else +# define BIGENDIAN_P 0 +#endif + #ifdef NATINT_PACK # define OFF16B(p) ((char*)(p) + (natint?0:(sizeof(short) - SIZE16))) # define OFF32B(p) ((char*)(p) + (natint?0:(sizeof(long) - SIZE32))) @@ -76,42 +82,80 @@ TOKEN_PASTE(swap,x)(xtype z) \ #ifndef swap16 #define swap16(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF)) #endif + +#ifndef swap32 +#define swap32(x) ((((x)&0xFF)<<24) \ + |(((x)>>24)&0xFF) \ + |(((x)&0x0000FF00)<<8) \ + |(((x)&0x00FF0000)>>8) ) +#endif + +#ifndef swap64 +#if SIZEOF_LONG == 8 +#define swap64(x) ((((x)&0x00000000000000FFL)<<56) \ + |(((x)&0xFF00000000000000L)>>56) \ + |(((x)&0x000000000000FF00L)<<40) \ + |(((x)&0x00FF000000000000L)>>40) \ + |(((x)&0x0000000000FF0000L)<<24) \ + |(((x)&0x0000FF0000000000L)>>24) \ + |(((x)&0x00000000FF000000L)<<8) \ + |(((x)&0x000000FF00000000L)>>8)) +#endif +#if defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8 +#define swap64(x) ((((x)&0x00000000000000FFLL)<<56) \ + |(((x)&0xFF00000000000000LL)>>56) \ + |(((x)&0x000000000000FF00LL)<<40) \ + |(((x)&0x00FF000000000000LL)>>40) \ + |(((x)&0x0000000000FF0000LL)<<24) \ + |(((x)&0x0000FF0000000000LL)>>24) \ + |(((x)&0x00000000FF000000LL)<<8) \ + |(((x)&0x000000FF00000000LL)>>8)) +#endif +#endif + #if SIZEOF_SHORT == 2 #define swaps(x) swap16(x) #else #if SIZEOF_SHORT == 4 -#define swaps(x) ((((x)&0xFF)<<24) \ - |(((x)>>24)&0xFF) \ - |(((x)&0x0000FF00)<<8) \ - |(((x)&0x00FF0000)>>8) ) +#define swaps(x) swap32(x) #else define_swapx(s,short) #endif #endif -#ifndef swap32 -#define swap32(x) ((((x)&0xFF)<<24) \ - |(((x)>>24)&0xFF) \ - |(((x)&0x0000FF00)<<8) \ - |(((x)&0x00FF0000)>>8) ) +#if SIZEOF_INT == 2 +#define swapi(x) swap16(x) +#else +#if SIZEOF_INT == 4 +#define swapi(x) swap32(x) +#else +define_swapx(i,int) +#endif #endif + #if SIZEOF_LONG == 4 #define swapl(x) swap32(x) #else #if SIZEOF_LONG == 8 -#define swapl(x) ((((x)&0x00000000000000FF)<<56) \ - |(((x)&0xFF00000000000000)>>56) \ - |(((x)&0x000000000000FF00)<<40) \ - |(((x)&0x00FF000000000000)>>40) \ - |(((x)&0x0000000000FF0000)<<24) \ - |(((x)&0x0000FF0000000000)>>24) \ - |(((x)&0x00000000FF000000)<<8) \ - |(((x)&0x000000FF00000000)>>8)) +#define swapl(x) swap64(x) #else define_swapx(l,long) #endif #endif +#ifdef HAVE_LONG_LONG + +#if SIZEOF_LONG_LONG == 4 +#define swapll(x) swap32(x) +#else +#if SIZEOF_LONG_LONG == 8 +#define swapll(x) swap64(x) +#else +define_swapx(ll,LONG_LONG) +#endif +#endif +#endif + #if SIZEOF_FLOAT == 4 #if SIZEOF_LONG == 4 /* SIZEOF_FLOAT == 4 == SIZEOF_LONG */ #define swapf(x) swapl(x) @@ -357,7 +401,7 @@ num2i32(VALUE x) #endif #ifdef HAVE_LONG_LONG -# define QUAD_SIZE sizeof(LONG_LONG) +# define QUAD_SIZE SIZEOF_LONG_LONG #else # define QUAD_SIZE 8 #endif @@ -1345,6 +1389,7 @@ pack_unpack(VALUE str, VALUE fmt) int natint; /* native integer */ #endif int block_p = rb_block_given_p(); + int signed_p, integer_size, bigendian_p; #define UNPACK_PUSH(item) do {\ VALUE item_val = (item);\ if (block_p) {\ @@ -1550,136 +1595,214 @@ pack_unpack(VALUE str, VALUE fmt) break; case 's': - PACK_LENGTH_ADJUST(short,2); - while (len-- > 0) { - short tmp = 0; - memcpy(OFF16(&tmp), s, NATINT_LEN(short,2)); - EXTEND16(tmp); - s += NATINT_LEN(short,2); - UNPACK_PUSH(INT2FIX(tmp)); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 1; + integer_size = NATINT_LEN(short, 2); + bigendian_p = BIGENDIAN_P; + goto unpack_integer; case 'S': - PACK_LENGTH_ADJUST(unsigned short,2); - while (len-- > 0) { - unsigned short tmp = 0; - memcpy(OFF16(&tmp), s, NATINT_LEN(unsigned short,2)); - s += NATINT_LEN(unsigned short,2); - UNPACK_PUSH(INT2FIX(tmp)); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 0; + integer_size = NATINT_LEN(short, 2); + bigendian_p = BIGENDIAN_P; + goto unpack_integer; case 'i': - PACK_LENGTH_ADJUST(int,sizeof(int)); - while (len-- > 0) { - int tmp; - memcpy(&tmp, s, sizeof(int)); - s += sizeof(int); - UNPACK_PUSH(INT2NUM(tmp)); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 1; + integer_size = sizeof(int); + bigendian_p = BIGENDIAN_P; + goto unpack_integer; case 'I': - PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int)); - while (len-- > 0) { - unsigned int tmp; - memcpy(&tmp, s, sizeof(unsigned int)); - s += sizeof(unsigned int); - UNPACK_PUSH(UINT2NUM(tmp)); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 0; + integer_size = sizeof(int); + bigendian_p = BIGENDIAN_P; + goto unpack_integer; case 'l': - PACK_LENGTH_ADJUST(long,4); - while (len-- > 0) { - long tmp = 0; - memcpy(OFF32(&tmp), s, NATINT_LEN(long,4)); - EXTEND32(tmp); - s += NATINT_LEN(long,4); - UNPACK_PUSH(LONG2NUM(tmp)); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 1; + integer_size = NATINT_LEN(long, 4); + bigendian_p = BIGENDIAN_P; + goto unpack_integer; case 'L': - PACK_LENGTH_ADJUST(unsigned long,4); - while (len-- > 0) { - unsigned long tmp = 0; - memcpy(OFF32(&tmp), s, NATINT_LEN(unsigned long,4)); - s += NATINT_LEN(unsigned long,4); - UNPACK_PUSH(ULONG2NUM(tmp)); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 0; + integer_size = NATINT_LEN(long, 4); + bigendian_p = BIGENDIAN_P; + goto unpack_integer; case 'q': - PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE); - while (len-- > 0) { - char *tmp = (char*)s; - s += QUAD_SIZE; - UNPACK_PUSH(rb_quad_unpack(tmp, 1)); - } - PACK_ITEM_ADJUST(); - break; - + signed_p = 1; + integer_size = QUAD_SIZE; + bigendian_p = BIGENDIAN_P; + goto unpack_integer; + case 'Q': - PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE); - while (len-- > 0) { - char *tmp = (char*)s; - s += QUAD_SIZE; - UNPACK_PUSH(rb_quad_unpack(tmp, 0)); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 0; + integer_size = QUAD_SIZE; + bigendian_p = BIGENDIAN_P; + goto unpack_integer; case 'n': - PACK_LENGTH_ADJUST(unsigned short,2); - while (len-- > 0) { - unsigned short tmp = 0; - memcpy(OFF16B(&tmp), s, NATINT_LEN(unsigned short,2)); - s += NATINT_LEN(unsigned short,2); - UNPACK_PUSH(UINT2NUM(ntohs(tmp))); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 0; + integer_size = 2; + bigendian_p = 1; + goto unpack_integer; case 'N': - PACK_LENGTH_ADJUST(unsigned long,4); - while (len-- > 0) { - unsigned long tmp = 0; - memcpy(OFF32B(&tmp), s, NATINT_LEN(unsigned long,4)); - s += NATINT_LEN(unsigned long,4); - UNPACK_PUSH(ULONG2NUM(ntohl(tmp))); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 0; + integer_size = 4; + bigendian_p = 1; + goto unpack_integer; case 'v': - PACK_LENGTH_ADJUST(unsigned short,2); - while (len-- > 0) { - unsigned short tmp = 0; - memcpy(&tmp, s, NATINT_LEN(unsigned short,2)); - s += NATINT_LEN(unsigned short,2); - UNPACK_PUSH(UINT2NUM(vtohs(tmp))); - } - PACK_ITEM_ADJUST(); - break; + signed_p = 0; + integer_size = 2; + bigendian_p = 0; + goto unpack_integer; case 'V': - PACK_LENGTH_ADJUST(unsigned long,4); - while (len-- > 0) { - unsigned long tmp = 0; - memcpy(&tmp, s, NATINT_LEN(long,4)); - s += NATINT_LEN(long,4); - UNPACK_PUSH(ULONG2NUM(vtohl(tmp))); + signed_p = 0; + integer_size = 4; + bigendian_p = 0; + goto unpack_integer; + + unpack_integer: + switch (integer_size) { + case SIZEOF_SHORT: + if (signed_p) { + PACK_LENGTH_ADJUST(short,sizeof(short)); + while (len-- > 0) { + short tmp; + memcpy(&tmp, s, sizeof(short)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swaps(tmp); + s += sizeof(short); + UNPACK_PUSH(INT2FIX(tmp)); + } + PACK_ITEM_ADJUST(); + } + else { + PACK_LENGTH_ADJUST(unsigned short,sizeof(unsigned short)); + while (len-- > 0) { + unsigned short tmp; + memcpy(&tmp, s, sizeof(unsigned short)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swaps(tmp); + s += sizeof(unsigned short); + UNPACK_PUSH(INT2FIX(tmp)); + } + PACK_ITEM_ADJUST(); + } + break; + +#if SIZEOF_SHORT != SIZEOF_INT + case SIZEOF_INT: + if (signed_p) { + PACK_LENGTH_ADJUST(int,sizeof(int)); + while (len-- > 0) { + int tmp; + memcpy(&tmp, s, sizeof(int)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swapi(tmp); + s += sizeof(int); + UNPACK_PUSH(INT2NUM(tmp)); + } + PACK_ITEM_ADJUST(); + } + else { + PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int)); + while (len-- > 0) { + unsigned int tmp; + memcpy(&tmp, s, sizeof(unsigned int)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swapi(tmp); + s += sizeof(unsigned int); + UNPACK_PUSH(UINT2NUM(tmp)); + } + PACK_ITEM_ADJUST(); + } + break; +#endif + +#if SIZEOF_INT != SIZEOF_LONG + case SIZEOF_LONG: + if (signed_p) { + PACK_LENGTH_ADJUST(long,sizeof(long)); + while (len-- > 0) { + long tmp; + memcpy(&tmp, s, sizeof(long)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swapl(tmp); + s += sizeof(long); + UNPACK_PUSH(LONG2NUM(tmp)); + } + PACK_ITEM_ADJUST(); + } + else { + PACK_LENGTH_ADJUST(unsigned long,sizeof(unsigned long)); + while (len-- > 0) { + unsigned long tmp; + memcpy(&tmp, s, sizeof(unsigned long)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swapl(tmp); + s += sizeof(unsigned long); + UNPACK_PUSH(ULONG2NUM(tmp)); + } + PACK_ITEM_ADJUST(); + } + break; +#endif + +#if defined(HAVE_LONG_LONG) && SIZEOF_LONG != SIZEOF_LONG_LONG + case SIZEOF_LONG_LONG: + if (signed_p) { + PACK_LENGTH_ADJUST(LONG_LONG,sizeof(LONG_LONG)); + while (len-- > 0) { + LONG_LONG tmp; + memcpy(&tmp, s, sizeof(LONG_LONG)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swapll(tmp); + s += sizeof(LONG_LONG); + UNPACK_PUSH(LL2NUM(tmp)); + } + PACK_ITEM_ADJUST(); + } + else { + PACK_LENGTH_ADJUST(unsigned LONG_LONG,sizeof(unsigned LONG_LONG)); + while (len-- > 0) { + unsigned LONG_LONG tmp; + memcpy(&tmp, s, sizeof(unsigned LONG_LONG)); + if (bigendian_p ^ BIGENDIAN_P) tmp = swapll(tmp); + s += sizeof(unsigned LONG_LONG); + UNPACK_PUSH(ULL2NUM(tmp)); + } + PACK_ITEM_ADJUST(); + } + break; + +#endif + +#if SIZEOF_LONG != QUAD_SIZE && (!defined(HAVE_LONG_LONG) || SIZEOF_LONG_LONG != QUAD_SIZE) + case QUAD_SIZE: + if (bigendian_p ^ BIGENDIAN_P) + rb_bug("unexpected endian"); + if (signed_p) { + PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE); + while (len-- > 0) { + char *tmp = (char*)s; + s += QUAD_SIZE; + UNPACK_PUSH(rb_quad_unpack(tmp, 1)); + } + PACK_ITEM_ADJUST(); + } + else { + PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE); + while (len-- > 0) { + char *tmp = (char*)s; + s += QUAD_SIZE; + UNPACK_PUSH(rb_quad_unpack(tmp, 0)); + } + PACK_ITEM_ADJUST(); + } + break; +#endif + + default: + rb_bug("unexpected intger size"); } - PACK_ITEM_ADJUST(); - break; case 'f': case 'F': diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb index 7cc3f0089e..518708c99d 100644 --- a/test/ruby/test_pack.rb +++ b/test/ruby/test_pack.rb @@ -493,7 +493,7 @@ class TestPack < Test::Unit::TestCase end def test_short_string - %w[n N v V s S l L q Q].each {|fmt| + %w[n N v V s S i I l L q Q s! S! i! I! l! l!].each {|fmt| str = [1].pack(fmt) assert_equal([1,nil], str.unpack("#{fmt}2")) } -- cgit v1.2.3