summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-06-08 08:42:55 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-06-08 08:42:55 +0000
commit98e7a2abca70fd044d5db7e1404c218e74abbd33 (patch)
tree760f5470b6df9dffbeb2f789a6512819b0bcd5dc
parent8c788b8a430ae3b683dec7246ec13fffd47dbe36 (diff)
merge revision(s) 27721:27725,27738:27740:
* pack.c: backport integer pack/unpack from 1.9 for [ruby-core:21937]. * configure.in: backport RUBY_DEFINT and fixed size integer checks. * ruby.h: include stdint.h if available. * bignum.c (rb_big_pack): defined.. (rb_big_unpack): defined. * intern.h (rb_big_pack): declared. (rb_big_unpack): declared. * pack.c (pack_pack): call rb_quad_pack to preserve RangeError. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_7@28220 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog18
-rw-r--r--bignum.c133
-rw-r--r--configure.in37
-rw-r--r--intern.h2
-rw-r--r--pack.c1050
-rw-r--r--ruby.h4
-rw-r--r--test/ruby/test_pack.rb221
-rw-r--r--version.h2
8 files changed, 975 insertions, 492 deletions
diff --git a/ChangeLog b/ChangeLog
index eb81de2473..66123e2a57 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+Tue Jun 8 17:32:37 2010 Tanaka Akira <akr@fsij.org>
+
+ * pack.c (pack_pack): call rb_quad_pack to preserve RangeError.
+
+Tue Jun 8 17:32:37 2010 Tanaka Akira <akr@fsij.org>
+
+ * pack.c: backport integer pack/unpack from 1.9 for [ruby-core:21937].
+
+ * configure.in: backport RUBY_DEFINT and fixed size integer checks.
+
+ * ruby.h: include stdint.h if available.
+
+ * bignum.c (rb_big_pack): defined..
+ (rb_big_unpack): defined.
+
+ * intern.h (rb_big_pack): declared.
+ (rb_big_unpack): declared.
+
Tue Jun 8 16:52:35 2010 Nobuyoshi Nakada <nobu@ruby-lang.org>
* regex.c (read_special): get rid of overrun.
diff --git a/bignum.c b/bignum.c
index 8e27369090..b9f552c4be 100644
--- a/bignum.c
+++ b/bignum.c
@@ -222,7 +222,110 @@ rb_int2inum(n)
return rb_int2big(n);
}
-#ifdef HAVE_LONG_LONG
+#if SIZEOF_LONG % SIZEOF_BDIGITS != 0
+# error unexpected SIZEOF_LONG : SIZEOF_BDIGITS ratio
+#endif
+
+/*
+ * buf is an array of long integers.
+ * buf is ordered from least significant word to most significant word.
+ * buf[0] is the least significant word and
+ * buf[num_longs-1] is the most significant word.
+ * This means words in buf is little endian.
+ * However each word in buf is native endian.
+ * (buf[i]&1) is the least significant bit and
+ * (buf[i]&(1<<(SIZEOF_LONG*CHAR_BIT-1))) is the most significant bit
+ * for each 0 <= i < num_longs.
+ * So buf is little endian at whole on a little endian machine.
+ * But buf is mixed endian on a big endian machine.
+ */
+void
+rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
+{
+ val = rb_to_int(val);
+ if (num_longs == 0)
+ return;
+ if (FIXNUM_P(val)) {
+ long i;
+ long tmp = FIX2LONG(val);
+ buf[0] = (unsigned long)tmp;
+ tmp = tmp < 0 ? ~0L : 0;
+ for (i = 1; i < num_longs; i++)
+ buf[i] = (unsigned long)tmp;
+ return;
+ }
+ else {
+ long len = RBIGNUM_LEN(val);
+ BDIGIT *ds = BDIGITS(val), *dend = ds + len;
+ long i, j;
+ for (i = 0; i < num_longs && ds < dend; i++) {
+ unsigned long l = 0;
+ for (j = 0; j < DIGSPERLONG && ds < dend; j++, ds++) {
+ l |= ((unsigned long)*ds << (j * BITSPERDIG));
+ }
+ buf[i] = l;
+ }
+ for (; i < num_longs; i++)
+ buf[i] = 0;
+ if (RBIGNUM_NEGATIVE_P(val)) {
+ for (i = 0; i < num_longs; i++) {
+ buf[i] = ~buf[i];
+ }
+ for (i = 0; i < num_longs; i++) {
+ buf[i]++;
+ if (buf[i] != 0)
+ return;
+ }
+ }
+ }
+}
+
+/* See rb_big_pack comment for endianness of buf. */
+VALUE
+rb_big_unpack(unsigned long *buf, long num_longs)
+{
+ while (2 <= num_longs) {
+ if (buf[num_longs-1] == 0 && (long)buf[num_longs-2] >= 0)
+ num_longs--;
+ else if (buf[num_longs-1] == ~0UL && (long)buf[num_longs-2] < 0)
+ num_longs--;
+ else
+ break;
+ }
+ if (num_longs == 0)
+ return INT2FIX(0);
+ else if (num_longs == 1)
+ return LONG2NUM((long)buf[0]);
+ else {
+ VALUE big;
+ BDIGIT *ds;
+ long len = num_longs * DIGSPERLONG;
+ long i;
+ big = bignew(len, 1);
+ ds = BDIGITS(big);
+ for (i = 0; i < num_longs; i++) {
+ unsigned long d = buf[i];
+#if SIZEOF_LONG == SIZEOF_BDIGITS
+ *ds++ = d;
+#else
+ int j;
+ for (j = 0; j < DIGSPERLONG; j++) {
+ *ds++ = BIGLO(d);
+ d = BIGDN(d);
+ }
+#endif
+ }
+ if ((long)buf[num_longs-1] < 0) {
+ get2comp(big);
+ RBIGNUM_SET_SIGN(big, 0);
+ }
+ return bignorm(big);
+ }
+}
+
+#define QUAD_SIZE 8
+
+#if SIZEOF_LONG_LONG == QUAD_SIZE && SIZEOF_BDIGITS*2 == SIZEOF_LONG_LONG
void
rb_quad_pack(buf, val)
@@ -295,7 +398,19 @@ rb_quad_unpack(buf, sign)
#else
-#define QUAD_SIZE 8
+static int
+quad_buf_complement(char *buf, size_t len)
+{
+ size_t i;
+ for (i = 0; i < len; i++)
+ buf[i] = ~buf[i];
+ for (i = 0; i < len; i++) {
+ buf[i]++;
+ if (buf[i] != 0)
+ return 0;
+ }
+ return 1;
+}
void
rb_quad_pack(buf, val)
@@ -314,12 +429,8 @@ rb_quad_pack(buf, val)
rb_raise(rb_eRangeError, "bignum too big to convert into `quad int'");
}
memcpy(buf, (char*)BDIGITS(val), len);
- if (!RBIGNUM(val)->sign) {
- len = QUAD_SIZE;
- while (len--) {
- *buf = ~*buf;
- buf++;
- }
+ if (RBIGNUM_NEGATIVE_P(val)) {
+ quad_buf_complement(buf, QUAD_SIZE);
}
}
@@ -334,14 +445,10 @@ rb_quad_unpack(buf, sign)
memcpy((char*)BDIGITS(big), buf, QUAD_SIZE);
if (sign && BNEG(buf)) {
- long len = QUAD_SIZE;
char *tmp = (char*)BDIGITS(big);
RBIGNUM(big)->sign = 0;
- while (len--) {
- *tmp = ~*tmp;
- tmp++;
- }
+ quad_buf_complement(tmp, QUAD_SIZE);
}
return bignorm(big);
diff --git a/configure.in b/configure.in
index 5abf2c3c52..91c2b544f7 100644
--- a/configure.in
+++ b/configure.in
@@ -544,6 +544,43 @@ AC_STRUCT_ST_BLKSIZE
AC_STRUCT_ST_BLOCKS
AC_STRUCT_ST_RDEV
+dnl RUBY_DEFINT TYPENAME, SIZE, [SIGNED-OR-UNSIGNED], [INCLUDES = DEFAULT-INCLUDES]
+AC_DEFUN([RUBY_DEFINT], [dnl
+AC_CACHE_CHECK([for $1], [rb_cv_type_$1],
+[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT([$4])
+typedef $1 t; int s = sizeof(t) == 42;])],
+ [rb_cv_type_$1=yes],
+ [AS_CASE([m4_bmatch([$2], [^[1-9][0-9]*$], $2, [$ac_cv_sizeof_]AS_TR_SH($2))],
+ ["1"], [ rb_cv_type_$1="m4_if([$3], [], [signed ], [$3 ])char"],
+ ["$ac_cv_sizeof_short"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])short"],
+ ["$ac_cv_sizeof_int"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])int"],
+ ["$ac_cv_sizeof_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long"],
+ ["$ac_cv_sizeof_long_long"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])long long"],
+ ["$ac_cv_sizeof___int64"], [ rb_cv_type_$1="m4_if([$3], [], [], [$3 ])__int64"],
+ [ rb_cv_type_$1=no])])])
+if test "${rb_cv_type_$1}" != no; then
+ AC_DEFINE([HAVE_]AS_TR_CPP($1), 1)
+ if test "${rb_cv_type_$1}" = yes; then
+ m4_bmatch([$2], [^[1-9][0-9]*$], [AC_CHECK_SIZEOF([$1], 0, [AC_INCLUDES_DEFAULT([$4])])],
+ [RUBY_CHECK_SIZEOF([$1], [$2], [], [AC_INCLUDES_DEFAULT([$4])])])
+ else
+ AC_DEFINE_UNQUOTED($1, [$rb_cv_type_$1])
+ AC_DEFINE_UNQUOTED([SIZEOF_]AS_TR_CPP($1), [SIZEOF_]AS_TR_CPP([$rb_cv_type_$1]))
+ fi
+fi
+])
+
+RUBY_DEFINT(int8_t, 1)
+RUBY_DEFINT(uint8_t, 1, unsigned)
+RUBY_DEFINT(int16_t, 2)
+RUBY_DEFINT(uint16_t, 2, unsigned)
+RUBY_DEFINT(int32_t, 4)
+RUBY_DEFINT(uint32_t, 4, unsigned)
+RUBY_DEFINT(int64_t, 8)
+RUBY_DEFINT(uint64_t, 8, unsigned)
+RUBY_DEFINT(int128_t, 16)
+RUBY_DEFINT(uint128_t, 16, unsigned)
+
dnl Checks for library functions.
AC_TYPE_GETGROUPS
AC_TYPE_SIGNAL
diff --git a/intern.h b/intern.h
index 47f0cddaa2..acae58db45 100644
--- a/intern.h
+++ b/intern.h
@@ -83,6 +83,8 @@ unsigned LONG_LONG rb_big2ull _((VALUE));
#endif /* HAVE_LONG_LONG */
void rb_quad_pack _((char*,VALUE));
VALUE rb_quad_unpack _((const char*,int));
+void rb_big_pack(VALUE val, unsigned long *buf, long num_longs);
+VALUE rb_big_unpack(unsigned long *buf, long num_longs);
VALUE rb_dbl2big _((double));
double rb_big2dbl _((VALUE));
VALUE rb_big_plus _((VALUE, VALUE));
diff --git a/pack.c b/pack.c
index 7a04673309..c2ece543a8 100644
--- a/pack.c
+++ b/pack.c
@@ -14,6 +14,12 @@
#include <sys/types.h>
#include <ctype.h>
+#define GCC_VERSION_SINCE(major, minor, patchlevel) \
+ (defined(__GNUC__) && !defined(__INTEL_COMPILER) && \
+ ((__GNUC__ > (major)) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ > (minor)) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ == (minor) && __GNUC_PATCHLEVEL__ >= (patchlevel))))
+
#define SIZE16 2
#define SIZE32 4
@@ -21,33 +27,40 @@
# define NATINT_PACK
#endif
-#ifdef NATINT_PACK
-# define OFF16B(p) ((char*)(p) + (natint?0:(sizeof(short) - SIZE16)))
-# define OFF32B(p) ((char*)(p) + (natint?0:(sizeof(long) - SIZE32)))
-# define NATINT_LEN(type,len) (natint?sizeof(type):(len))
-# ifdef WORDS_BIGENDIAN
-# define OFF16(p) OFF16B(p)
-# define OFF32(p) OFF32B(p)
-# endif
-# define NATINT_HTOVS(x) (natint?htovs(x):htov16(x))
-# define NATINT_HTOVL(x) (natint?htovl(x):htov32(x))
-# define NATINT_HTONS(x) (natint?htons(x):hton16(x))
-# define NATINT_HTONL(x) (natint?htonl(x):hton32(x))
+#ifdef DYNAMIC_ENDIAN
+ /* for universal binary of NEXTSTEP and MacOS X */
+ /* useless since autoconf 2.63? */
+ static int
+ is_bigendian(void)
+ {
+ static int init = 0;
+ static int endian_value;
+ char *p;
+
+ if (init) return endian_value;
+ init = 1;
+ p = (char*)&init;
+ return endian_value = p[0]?0:1;
+ }
+# define BIGENDIAN_P() (is_bigendian())
+#elif defined(WORDS_BIGENDIAN)
+# define BIGENDIAN_P() 1
#else
-# define NATINT_LEN(type,len) sizeof(type)
-# define NATINT_HTOVS(x) htovs(x)
-# define NATINT_HTOVL(x) htovl(x)
-# define NATINT_HTONS(x) htons(x)
-# define NATINT_HTONL(x) htonl(x)
+# define BIGENDIAN_P() 0
#endif
-#ifndef OFF16
-# define OFF16(p) (char*)(p)
-# define OFF32(p) (char*)(p)
+#ifdef NATINT_PACK
+# define NATINT_LEN(type,len) (natint?(int)sizeof(type):(int)(len))
+#else
+# define NATINT_LEN(type,len) ((int)sizeof(type))
#endif
-#ifndef OFF16B
-# define OFF16B(p) (char*)(p)
-# define OFF32B(p) (char*)(p)
+
+#if SIZEOF_LONG == 8
+# define INT64toNUM(x) LONG2NUM(x)
+# define UINT64toNUM(x) ULONG2NUM(x)
+#elif defined(HAVE_LONG_LONG) && SIZEOF_LONG_LONG == 8
+# define INT64toNUM(x) LL2NUM(x)
+# define UINT64toNUM(x) ULL2NUM(x)
#endif
#define define_swapx(x, xtype) \
@@ -73,262 +86,185 @@ TOKEN_PASTE(swap,x)(z) \
return r; \
}
+#if GCC_VERSION_SINCE(4,3,0)
+# define swap32(x) __builtin_bswap32(x)
+# define swap64(x) __builtin_bswap64(x)
+#endif
+
#ifndef swap16
-#define swap16(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+# define swap16(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
#endif
-#if SIZEOF_SHORT == 2
-#define swaps(x) swap16(x)
-#else
-#if SIZEOF_SHORT == 4
-#define swaps(x) ((((x)&0xFF)<<24) \
+
+#ifndef swap32
+# define swap32(x) ((((x)&0xFF)<<24) \
|(((x)>>24)&0xFF) \
|(((x)&0x0000FF00)<<8) \
|(((x)&0x00FF0000)>>8) )
-#else
-define_swapx(s,short)
#endif
+
+#ifndef swap64
+# ifdef HAVE_INT64_T
+# define byte_in_64bit(n) ((uint64_t)0xff << (n))
+# define swap64(x) ((((x)&byte_in_64bit(0))<<56) \
+ |(((x)>>56)&0xFF) \
+ |(((x)&byte_in_64bit(8))<<40) \
+ |(((x)&byte_in_64bit(48))>>40) \
+ |(((x)&byte_in_64bit(16))<<24) \
+ |(((x)&byte_in_64bit(40))>>24) \
+ |(((x)&byte_in_64bit(24))<<8) \
+ |(((x)&byte_in_64bit(32))>>8))
+# endif
#endif
-#ifndef swap32
-#define swap32(x) ((((x)&0xFF)<<24) \
- |(((x)>>24)&0xFF) \
- |(((x)&0x0000FF00)<<8) \
- |(((x)&0x00FF0000)>>8) )
+#if SIZEOF_SHORT == 2
+# define swaps(x) swap16(x)
+#elif SIZEOF_SHORT == 4
+# define swaps(x) swap32(x)
+#else
+ define_swapx(s,short)
#endif
-#if SIZEOF_LONG == 4
-#define swapl(x) swap32(x)
+
+#if SIZEOF_INT == 2
+# define swapi(x) swap16(x)
+#elif SIZEOF_INT == 4
+# define swapi(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_swapx(i,int)
+#endif
+
+#if SIZEOF_LONG == 4
+# define swapl(x) swap32(x)
+#elif SIZEOF_LONG == 8
+# define swapl(x) swap64(x)
#else
-define_swapx(l,long)
+ define_swapx(l,long)
#endif
+
+#ifdef HAVE_LONG_LONG
+# if SIZEOF_LONG_LONG == 8
+# define swapll(x) swap64(x)
+# else
+ define_swapx(ll,LONG_LONG)
+# endif
#endif
#if SIZEOF_FLOAT == 4
-#if SIZEOF_LONG == 4 /* SIZEOF_FLOAT == 4 == SIZEOF_LONG */
-#define swapf(x) swapl(x)
-#define FLOAT_SWAPPER unsigned long
-#else
-#if SIZEOF_SHORT == 4 /* SIZEOF_FLOAT == 4 == SIZEOF_SHORT */
-#define swapf(x) swaps(x)
-#define FLOAT_SWAPPER unsigned short
-#else /* SIZEOF_FLOAT == 4 but undivide by known size of int */
-define_swapx(f,float)
-#endif /* #if SIZEOF_SHORT == 4 */
-#endif /* #if SIZEOF_LONG == 4 */
+# ifdef HAVE_UINT32_T
+# define swapf(x) swap32(x)
+# define FLOAT_SWAPPER uint32_t
+# else /* SIZEOF_FLOAT == 4 but undivide by known size of int */
+ define_swapx(f,float)
+# endif
#else /* SIZEOF_FLOAT != 4 */
-define_swapx(f,float)
+ define_swapx(f,float)
#endif /* #if SIZEOF_FLOAT == 4 */
#if SIZEOF_DOUBLE == 8
-#if SIZEOF_LONG == 8 /* SIZEOF_DOUBLE == 8 == SIZEOF_LONG */
-#define swapd(x) swapl(x)
-#define DOUBLE_SWAPPER unsigned long
-#else
-#if SIZEOF_LONG == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_LONG */
-static double
-swapd(d)
- const double d;
-{
- double dtmp = d;
- unsigned long utmp[2];
- unsigned long utmp0;
-
- utmp[0] = 0; utmp[1] = 0;
- memcpy(utmp,&dtmp,sizeof(double));
- utmp0 = utmp[0];
- utmp[0] = swapl(utmp[1]);
- utmp[1] = swapl(utmp0);
- memcpy(&dtmp,utmp,sizeof(double));
- return dtmp;
-}
-#else
-#if SIZEOF_SHORT == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_SHORT */
-static double
-swapd(d)
- const double d;
-{
- double dtmp = d;
- unsigned short utmp[2];
- unsigned short utmp0;
-
- utmp[0] = 0; utmp[1] = 0;
- memcpy(utmp,&dtmp,sizeof(double));
- utmp0 = utmp[0];
- utmp[0] = swaps(utmp[1]);
- utmp[1] = swaps(utmp0);
- memcpy(&dtmp,utmp,sizeof(double));
- return dtmp;
-}
-#else /* SIZEOF_DOUBLE == 8 but undivied by known size of int */
-define_swapx(d, double)
-#endif /* #if SIZEOF_SHORT == 4 */
-#endif /* #if SIZEOF_LONG == 4 */
-#endif /* #if SIZEOF_LONG == 8 */
+# ifdef HAVE_UINT64_T /* SIZEOF_DOUBLE == 8 == SIZEOF_UINT64_T */
+# define swapd(x) swap64(x)
+# define DOUBLE_SWAPPER uint64_t
+# else
+# if SIZEOF_LONG == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_LONG */
+ static double
+ swapd(const double d)
+ {
+ double dtmp = d;
+ unsigned long utmp[2];
+ unsigned long utmp0;
+
+ utmp[0] = 0; utmp[1] = 0;
+ memcpy(utmp,&dtmp,sizeof(double));
+ utmp0 = utmp[0];
+ utmp[0] = swapl(utmp[1]);
+ utmp[1] = swapl(utmp0);
+ memcpy(&dtmp,utmp,sizeof(double));
+ return dtmp;
+ }
+# elif SIZEOF_SHORT == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_SHORT */
+ static double
+ swapd(const double d)
+ {
+ double dtmp = d;
+ unsigned short utmp[2];
+ unsigned short utmp0;
+
+ utmp[0] = 0; utmp[1] = 0;
+ memcpy(utmp,&dtmp,sizeof(double));
+ utmp0 = utmp[0];
+ utmp[0] = swaps(utmp[1]);
+ utmp[1] = swaps(utmp0);
+ memcpy(&dtmp,utmp,sizeof(double));
+ return dtmp;
+ }
+# else /* SIZEOF_DOUBLE == 8 but undivide by known size of int */
+ define_swapx(d, double)
+# endif
+# endif /* #if SIZEOF_LONG == 8 */
#else /* SIZEOF_DOUBLE != 8 */
-define_swapx(d, double)
+ define_swapx(d, double)
#endif /* #if SIZEOF_DOUBLE == 8 */
#undef define_swapx
-#ifdef DYNAMIC_ENDIAN
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-static int
-endian()
-{
- static int init = 0;
- static int endian_value;
- char *p;
-
- if (init) return endian_value;
- init = 1;
- p = (char*)&init;
- return endian_value = p[0]?0:1;
-}
-
-#define ntohs(x) (endian()?(x):swaps(x))
-#define ntohl(x) (endian()?(x):swapl(x))
-#define ntohf(x) (endian()?(x):swapf(x))
-#define ntohd(x) (endian()?(x):swapd(x))
-#define htons(x) (endian()?(x):swaps(x))
-#define htonl(x) (endian()?(x):swapl(x))
-#define htonf(x) (endian()?(x):swapf(x))
-#define htond(x) (endian()?(x):swapd(x))
-#define htovs(x) (endian()?swaps(x):(x))
-#define htovl(x) (endian()?swapl(x):(x))
-#define htovf(x) (endian()?swapf(x):(x))
-#define htovd(x) (endian()?swapd(x):(x))
-#define vtohs(x) (endian()?swaps(x):(x))
-#define vtohl(x) (endian()?swapl(x):(x))
-#define vtohf(x) (endian()?swapf(x):(x))
-#define vtohd(x) (endian()?swapd(x):(x))
-# ifdef NATINT_PACK
-#define htov16(x) (endian()?swap16(x):(x))
-#define htov32(x) (endian()?swap32(x):(x))
-#define hton16(x) (endian()?(x):swap16(x))
-#define hton32(x) (endian()?(x):swap32(x))
-# endif
-#else
-#ifdef WORDS_BIGENDIAN
-#ifndef ntohs
-#define ntohs(x) (x)
-#define ntohl(x) (x)
-#define htons(x) (x)
-#define htonl(x) (x)
-#endif
-#define ntohf(x) (x)
-#define ntohd(x) (x)
-#define htonf(x) (x)
-#define htond(x) (x)
-#define htovs(x) swaps(x)
-#define htovl(x) swapl(x)
-#define htovf(x) swapf(x)
-#define htovd(x) swapd(x)
-#define vtohs(x) swaps(x)
-#define vtohl(x) swapl(x)
-#define vtohf(x) swapf(x)
-#define vtohd(x) swapd(x)
-# ifdef NATINT_PACK
-#define htov16(x) swap16(x)
-#define htov32(x) swap32(x)
-#define hton16(x) (x)
-#define hton32(x) (x)
-# endif
-#else /* LITTLE ENDIAN */
-#ifdef ntohs
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-#define ntohs(x) swaps(x)
-#define ntohl(x) swapl(x)
-#define htons(x) swaps(x)
-#define htonl(x) swapl(x)
-#define ntohf(x) swapf(x)
-#define ntohd(x) swapd(x)
-#define htonf(x) swapf(x)
-#define htond(x) swapd(x)
-#define htovs(x) (x)
-#define htovl(x) (x)
-#define htovf(x) (x)
-#define htovd(x) (x)
-#define vtohs(x) (x)
-#define vtohl(x) (x)
-#define vtohf(x) (x)
-#define vtohd(x) (x)
-# ifdef NATINT_PACK
-#define htov16(x) (x)
-#define htov32(x) (x)
-#define hton16(x) swap16(x)
-#define hton32(x) swap32(x)
-# endif
-#endif
-#endif
+#define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x))
+#define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x))
+#define rb_htonf(x) (BIGENDIAN_P()?(x):swapf(x))
+#define rb_htond(x) (BIGENDIAN_P()?(x):swapd(x))
+#define rb_htovf(x) (BIGENDIAN_P()?swapf(x):(x))
+#define rb_htovd(x) (BIGENDIAN_P()?swapd(x):(x))
+#define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x))
+#define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x))
#ifdef FLOAT_SWAPPER
#define FLOAT_CONVWITH(y) FLOAT_SWAPPER y;
#define HTONF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = htonf((FLOAT_SWAPPER)y), \
+ y = rb_htonf((FLOAT_SWAPPER)y), \
memcpy(&x,&y,sizeof(float)), \
x)
#define HTOVF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = htovf((FLOAT_SWAPPER)y), \
+ y = rb_htovf((FLOAT_SWAPPER)y), \
memcpy(&x,&y,sizeof(float)), \
x)
#define NTOHF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = ntohf((FLOAT_SWAPPER)y), \
+ y = rb_ntohf((FLOAT_SWAPPER)y), \
memcpy(&x,&y,sizeof(float)), \
x)
#define VTOHF(x,y) (memcpy(&y,&x,sizeof(float)), \
- y = vtohf((FLOAT_SWAPPER)y), \
+ y = rb_vtohf((FLOAT_SWAPPER)y), \
memcpy(&x,&y,sizeof(float)), \
x)
#else
#define FLOAT_CONVWITH(y)
-#define HTONF(x,y) htonf(x)
-#define HTOVF(x,y) htovf(x)
-#define NTOHF(x,y) ntohf(x)
-#define VTOHF(x,y) vtohf(x)
+# define HTONF(x,y) rb_htonf(x)
+# define HTOVF(x,y) rb_htovf(x)
+# define NTOHF(x,y) rb_ntohf(x)
+# define VTOHF(x,y) rb_vtohf(x)
#endif
#ifdef DOUBLE_SWAPPER
#define DOUBLE_CONVWITH(y) DOUBLE_SWAPPER y;
#define HTOND(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = htond((DOUBLE_SWAPPER)y), \
+ y = rb_htond((DOUBLE_SWAPPER)y), \
memcpy(&x,&y,sizeof(double)), \
x)
#define HTOVD(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = htovd((DOUBLE_SWAPPER)y), \
+ y = rb_htovd((DOUBLE_SWAPPER)y), \
memcpy(&x,&y,sizeof(double)), \
x)
#define NTOHD(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = ntohd((DOUBLE_SWAPPER)y), \
+ y = rb_ntohd((DOUBLE_SWAPPER)y), \
memcpy(&x,&y,sizeof(double)), \
x)
#define VTOHD(x,y) (memcpy(&y,&x,sizeof(double)), \
- y = vtohd((DOUBLE_SWAPPER)y), \
+ y = rb_vtohd((DOUBLE_SWAPPER)y), \
memcpy(&x,&y,sizeof(double)), \
x)
#else
#define DOUBLE_CONVWITH(y)
-#define HTOND(x,y) htond(x)
-#define HTOVD(x,y) htovd(x)
-#define NTOHD(x,y) ntohd(x)
-#define VTOHD(x,y) vtohd(x)
+# define HTOND(x,y) rb_htond(x)
+# define HTOVD(x,y) rb_htovd(x)
+# define NTOHD(x,y) rb_ntohd(x)
+# define VTOHD(x,y) rb_vtohd(x)
#endif
unsigned long rb_big2ulong_pack _((VALUE x));
@@ -359,11 +295,10 @@ num2i32(x)
# define EXTEND16(x) do { if (!natint) {(x) = (short)(((1<<15)-1-(x))^~(~0<<15));}} while(0)
#endif
-#ifdef HAVE_LONG_LONG
-# define QUAD_SIZE sizeof(LONG_LONG)
-#else
-# define QUAD_SIZE 8
-#endif
+#define QUAD_SIZE 8
+#define MAX_INTEGER_PACK_SIZE 8
+/* #define FORCE_BIG_PACK */
+
static const char toofew[] = "too few arguments";
static void encodes _((VALUE,const char*,long,int));
@@ -397,44 +332,67 @@ static unsigned long utf8_to_uv _((char*,long*));
*
* Directives for +pack+.
*
- * Directive Meaning
- * ---------------------------------------------------------------
- * @ | Moves to absolute position
- * A | ASCII string (space padded, count is width)
- * a | ASCII string (null padded, count is width)
- * B | Bit string (descending bit order)
- * b | Bit string (ascending bit order)
- * C | Unsigned char
- * c | Char
- * D, d | Double-precision float, native format
- * E | Double-precision float, little-endian byte order
- * e | Single-precision float, little-endian byte order
- * F, f | Single-precision float, native format
- * G | Double-precision float, network (big-endian) byte order
- * g | Single-precision float, network (big-endian) byte order
- * H | Hex string (high nibble first)
- * h | Hex string (low nibble first)
- * I | Unsigned integer
- * i | Integer
- * L | Unsigned long
- * l | Long
- * M | Quoted printable, MIME encoding (see RFC2045)
- * m | Base64 encoded string
- * N | Long, network (big-endian) byte order
- * n | Short, network (big-endian) byte-order
- * P | Pointer to a structure (fixed-length string)
- * p | Pointer to a null-terminated string
- * Q, q | 64-bit number
- * S | Unsigned short
- * s | Short
- * U | UTF-8
- * u | UU-encoded string
- * V | Long, little-endian byte order
- * v | Short, little-endian byte order
- * w | BER-compressed integer\fnm
- * X | Back up a byte
- * x | Null byte
- * Z | Same as ``a'', except that null is added with *
+ * Integer | Array |
+ * Directive | Element | Meaning
+ * ------------------------------------------------------------------------
+ * C | Integer | 8-bit unsigned integer (unsigned char)
+ * S | Integer | 16-bit unsigned integer, native endian (uint16_t)
+ * L | Integer | 32-bit unsigned integer, native endian (uint32_t)
+ * Q | Integer | 64-bit unsigned integer, native endian (uint64_t)
+ * | |
+ * c | Integer | 8-bit signed integer (char)
+ * s | Integer | 16-bit signed integer, native endian (int16_t)
+ * l | Integer | 32-bit signed integer, native endian (int32_t)
+ * q | Integer | 64-bit signed integer, native endian (int64_t)
+ * | |
+ * S_ | Integer | unsigned short, native endian
+ * I, I_ | Integer | unsigned int, native endian
+ * L_ | Integer | unsigned long, native endian
+ * | |
+ * s_ | Integer | signed short, native endian
+ * i, i_ | Integer | signed int, native endian
+ * l_ | Integer | signed long, native endian
+ * | |
+ * n | Integer | 16-bit unsigned integer, network (big-endian) byte order
+ * N | Integer | 32-bit unsigned integer, network (big-endian) byte order
+ * v | Integer | 16-bit unsigned integer, VAX (little-endian) byte order
+ * V | Integer | 32-bit unsigned integer, VAX (little-endian) byte order
+ * | |
+ * U | Integer | UTF-8 character
+ * w | Integer | BER-compressed integer
+ *
+ * Float | |
+ * Directive | | Meaning
+ * ------------------------------------------------------------------------
+ * D, d | Float | double-precision float, native format
+ * F, f | Float | single-precision float, native format
+ * E | Float | double-precision float, little-endian byte order
+ * e | Float | single-precision float, little-endian byte order
+ * G | Float | double-precision float, network (big-endian) byte order
+ * g | Float | single-precision float, network (big-endian) byte order
+ *
+ * String | |
+ * Directive | | Meaning
+ * ------------------------------------------------------------------------
+ * A | String | arbitrary binary string (space padded, count is width)
+ * a | String | arbitrary binary string (null padded, count is width)
+ * Z | String | same as ``a'', except that null is added with *
+ * B | String | bit string (MSB first)
+ * b | String | bit string (LSB first)
+ * H | String | hex string (high nibble first)
+ * h | String | hex string (low nibble first)
+ * u | String | UU-encoded string
+ * M | String | quoted printable, MIME encoding (see RFC2045)
+ * m | String | base64 encoded string (see RFC 2045, count is width)
+ * P | String | pointer to a structure (fixed-length string)
+ * p | String | pointer to a null-terminated string
+ *
+ * Misc. | |
+ * Directive | | Meaning
+ * ------------------------------------------------------------------------
+ * @ | --- | moves to absolute position
+ * X | --- | back up a byte
+ * x | --- | null byte
*/
static VALUE
@@ -451,6 +409,7 @@ pack_pack(ary, fmt)
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
+ int signed_p, integer_size, bigendian_p;
StringValue(fmt);
p = RSTRING(fmt)->ptr;
@@ -682,92 +641,163 @@ pack_pack(ary, fmt)
break;
case 's': /* signed short */
- case 'S': /* unsigned short */
- while (len-- > 0) {
- short s;
+ signed_p = 1;
+ integer_size = NATINT_LEN(short, 2);
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
- from = NEXTFROM;
- s = num2i32(from);
- rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
- }
- break;
+ case 'S': /* unsigned short */
+ signed_p = 0;
+ integer_size = NATINT_LEN(short, 2);
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
case 'i': /* signed int */
- case 'I': /* unsigned int */
- while (len-- > 0) {
- long i;
+ signed_p = 1;
+ integer_size = (int)sizeof(int);
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
- from = NEXTFROM;
- i = num2i32(from);
- rb_str_buf_cat(res, OFF32(&i), NATINT_LEN(int,4));
- }
- break;
+ case 'I': /* unsigned int */
+ signed_p = 0;
+ integer_size = (int)sizeof(int);
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
case 'l': /* signed long */
- case 'L': /* unsigned long */
- while (len-- > 0) {
- long l;
+ signed_p = 1;
+ integer_size = NATINT_LEN(long, 4);
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
- from = NEXTFROM;
- l = num2i32(from);
- rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
- }
- break;
+ case 'L': /* unsigned long */
+ signed_p = 0;
+ integer_size = NATINT_LEN(long, 4);
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
case 'q': /* signed quad (64bit) int */
- case 'Q': /* unsigned quad (64bit) int */
- while (len-- > 0) {
- char tmp[QUAD_SIZE];
+ signed_p = 1;
+ integer_size = 8;
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
- from = NEXTFROM;
- rb_quad_pack(tmp, from);
- rb_str_buf_cat(res, (char*)&tmp, QUAD_SIZE);
- }
- break;
+ case 'Q': /* unsigned quad (64bit) int */
+ signed_p = 0;
+ integer_size = 8;
+ bigendian_p = BIGENDIAN_P();
+ goto pack_integer;
case 'n': /* unsigned short (network byte-order) */
- while (len-- > 0) {
- unsigned short s;
-
- from = NEXTFROM;
- s = num2i32(from);
- s = NATINT_HTONS(s);
- rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
- }
- break;
+ signed_p = 0;
+ integer_size = 2;
+ bigendian_p = 1;
+ goto pack_integer;
case 'N': /* unsigned long (network byte-order) */
- while (len-- > 0) {
- unsigned long l;
-
- from = NEXTFROM;
- l = num2i32(from);
- l = NATINT_HTONL(l);
- rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
- }
- break;
+ signed_p = 0;
+ integer_size = 4;
+ bigendian_p = 1;
+ goto pack_integer;
case 'v': /* unsigned short (VAX byte-order) */
- while (len-- > 0) {
- unsigned short s;
-
- from = NEXTFROM;
- s = num2i32(from);
- s = NATINT_HTOVS(s);
- rb_str_buf_cat(res, OFF16(&s), NATINT_LEN(short,2));
- }
- break;
+ signed_p = 0;
+ integer_size = 2;
+ bigendian_p = 0;
+ goto pack_integer;
case 'V': /* unsigned long (VAX byte-order) */
- while (len-- > 0) {
- unsigned long l;
+ signed_p = 0;
+ integer_size = 4;
+ bigendian_p = 0;
+ goto pack_integer;
+
+ pack_integer:
+ switch (integer_size) {
+#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
+ case SIZEOF_INT16_T:
+ while (len-- > 0) {
+ union {
+ int16_t i;
+ char a[sizeof(int16_t)];
+ } v;
+
+ from = NEXTFROM;
+ v.i = (int16_t)num2i32(from);
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
+ rb_str_buf_cat(res, v.a, sizeof(int16_t));
+ }
+ break;
+#endif
- from = NEXTFROM;
- l = num2i32(from);
- l = NATINT_HTOVL(l);
- rb_str_buf_cat(res, OFF32(&l), NATINT_LEN(long,4));
- }
- break;
+#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
+ case SIZEOF_INT32_T:
+ while (len-- > 0) {
+ union {
+ int32_t i;
+ char a[sizeof(int32_t)];
+ } v;
+
+ from = NEXTFROM;
+ v.i = (int32_t)num2i32(from);
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
+ rb_str_buf_cat(res, v.a, sizeof(int32_t));
+ }
+ break;
+#endif
+
+#if defined(HAVE_INT64_T) && SIZEOF_LONG == SIZEOF_INT64_T && !defined(FORCE_BIG_PACK)
+ case SIZEOF_INT64_T:
+ while (len-- > 0) {
+ union {
+ int64_t i;
+ char a[sizeof(int64_t)];
+ } v;
+
+ from = NEXTFROM;
+ v.i = num2i32(from); /* can return 64bit value if SIZEOF_LONG == SIZEOF_INT64_T */
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
+ rb_str_buf_cat(res, v.a, sizeof(int64_t));
+ }
+ break;
+#endif
+
+ default:
+ if (integer_size > MAX_INTEGER_PACK_SIZE)
+ rb_bug("unexpected intger size for pack: %d", integer_size);
+ while (len-- > 0) {
+ union {
+ unsigned long i[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG];
+ char a[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG-1)/SIZEOF_LONG*SIZEOF_LONG];
+ } v;
+ int num_longs = (integer_size+SIZEOF_LONG-1)/SIZEOF_LONG;
+ int i;
+
+ from = NEXTFROM;
+ from = rb_to_int(from);
+ if (integer_size == QUAD_SIZE)
+ rb_quad_pack(v.a, from); /* RangeError compatibility for Ruby 1.8. */
+ rb_big_pack(from, v.i, num_longs);
+ if (bigendian_p) {
+ for (i = 0; i < num_longs/2; i++) {
+ unsigned long t = v.i[i];
+ v.i[i] = v.i[num_longs-1-i];
+ v.i[num_longs-1-i] = t;
+ }
+ }
+ if (bigendian_p != BIGENDIAN_P()) {
+ for (i = 0; i < num_longs; i++)
+ v.i[i] = swapl(v.i[i]);
+ }
+ rb_str_buf_cat(res,
+ bigendian_p ?
+ v.a + sizeof(long)*num_longs - integer_size :
+ v.a,
+ integer_size);
+ }
+ break;
+ }
+ break;
case 'f': /* single precision float in native format */
case 'F': /* ditto */
@@ -1132,26 +1162,19 @@ hex2num(c)
}
#define PACK_LENGTH_ADJUST_SIZE(sz) do { \
- tmp = 0; \
- if (len > (send-s)/sz) { \
+ tmp_len = 0; \
+ if (len > (long)((send-s)/sz)) { \
if (!star) { \
- tmp = len-(send-s)/sz; \
+ tmp_len = len-(send-s)/sz; \
} \
len = (send-s)/sz; \
} \
} while (0)
-#ifdef NATINT_PACK
-#define PACK_LENGTH_ADJUST(type,sz) do { \
- int t__len = NATINT_LEN(type,(sz)); \
- PACK_LENGTH_ADJUST_SIZE(t__len); \
+#define PACK_ITEM_ADJUST() do { \
+ if (tmp_len > 0) \
+ rb_ary_store(ary, RARRAY_LEN(ary)+tmp_len-1, Qnil); \
} while (0)
-#else
-#define PACK_LENGTH_ADJUST(type,sz) \
- PACK_LENGTH_ADJUST_SIZE(sizeof(type))
-#endif
-
-#define PACK_ITEM_ADJUST() while (tmp--) rb_ary_push(ary, Qnil)
static VALUE
infected_str_new(ptr, len, str)
@@ -1312,11 +1335,12 @@ pack_unpack(str, fmt)
char *p, *pend;
VALUE ary;
char type;
- long len;
- int tmp, star;
+ long len, tmp_len;
+ int star;
#ifdef NATINT_PACK
int natint; /* native integer */
#endif
+ int signed_p, integer_size, bigendian_p;
StringValue(str);
StringValue(fmt);
@@ -1490,7 +1514,7 @@ pack_unpack(str, fmt)
break;
case 'c':
- PACK_LENGTH_ADJUST(char,sizeof(char));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(char));
while (len-- > 0) {
int c = *s++;
if (c > (char)127) c-=256;
@@ -1500,7 +1524,7 @@ pack_unpack(str, fmt)
break;
case 'C':
- PACK_LENGTH_ADJUST(unsigned char,sizeof(unsigned char));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(unsigned char));
while (len-- > 0) {
unsigned char c = *s++;
rb_ary_push(ary, INT2FIX(c));
@@ -1509,139 +1533,221 @@ pack_unpack(str, 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);
- rb_ary_push(ary, 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);
- rb_ary_push(ary, 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);
- rb_ary_push(ary, INT2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
+ signed_p = 1;
+ integer_size = (int)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);
- rb_ary_push(ary, UINT2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
+ signed_p = 0;
+ integer_size = (int)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);
- rb_ary_push(ary, LONG2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- 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);
- rb_ary_push(ary, ULONG2NUM(tmp));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'q':
- PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
- while (len-- > 0) {
- char *tmp = (char*)s;
- s += QUAD_SIZE;
- rb_ary_push(ary, rb_quad_unpack(tmp, 1));
- }
- PACK_ITEM_ADJUST();
- break;
-
- case 'Q':
- PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE);
- while (len-- > 0) {
- char *tmp = (char*)s;
- s += QUAD_SIZE;
- rb_ary_push(ary, rb_quad_unpack(tmp, 0));
- }
- break;
+ signed_p = 1;
+ integer_size = NATINT_LEN(long, 4);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'L':
+ signed_p = 0;
+ integer_size = NATINT_LEN(long, 4);
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'q':
+ signed_p = 1;
+ integer_size = QUAD_SIZE;
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'Q':
+ signed_p = 0;
+ integer_size = QUAD_SIZE;
+ bigendian_p = BIGENDIAN_P();
+ goto unpack_integer;
+
+ case 'n':
+ signed_p = 0;
+ integer_size = 2;
+ bigendian_p = 1;
+ goto unpack_integer;
+
+ case 'N':
+ signed_p = 0;
+ integer_size = 4;
+ bigendian_p = 1;
+ goto unpack_integer;
+
+ case 'v':
+ signed_p = 0;
+ integer_size = 2;
+ bigendian_p = 0;
+ goto unpack_integer;
+
+ case 'V':
+ signed_p = 0;
+ integer_size = 4;
+ bigendian_p = 0;
+ goto unpack_integer;
+
+ unpack_integer:
+ switch (integer_size) {
+#if defined(HAVE_INT16_T) && !defined(FORCE_BIG_PACK)
+ case SIZEOF_INT16_T:
+ if (signed_p) {
+ PACK_LENGTH_ADJUST_SIZE(sizeof(int16_t));
+ while (len-- > 0) {
+ union {
+ int16_t i;
+ char a[sizeof(int16_t)];
+ } v;
+ memcpy(v.a, s, sizeof(int16_t));
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
+ s += sizeof(int16_t);
+ rb_ary_push(ary, INT2FIX(v.i));
+ }
+ PACK_ITEM_ADJUST();
+ }
+ else {
+ PACK_LENGTH_ADJUST_SIZE(sizeof(uint16_t));
+ while (len-- > 0) {
+ union {
+ uint16_t i;
+ char a[sizeof(uint16_t)];
+ } v;
+ memcpy(v.a, s, sizeof(uint16_t));
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap16(v.i);
+ s += sizeof(uint16_t);
+ rb_ary_push(ary, INT2FIX(v.i));
+ }
+ PACK_ITEM_ADJUST();
+ }
+ break;
+#endif
- 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);
- rb_ary_push(ary, UINT2NUM(ntohs(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
+#if defined(HAVE_INT32_T) && !defined(FORCE_BIG_PACK)
+ case SIZEOF_INT32_T:
+ if (signed_p) {
+ PACK_LENGTH_ADJUST_SIZE(sizeof(int32_t));
+ while (len-- > 0) {
+ union {
+ int32_t i;
+ char a[sizeof(int32_t)];
+ } v;
+ memcpy(v.a, s, sizeof(int32_t));
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
+ s += sizeof(int32_t);
+ rb_ary_push(ary, INT2NUM(v.i));
+ }
+ PACK_ITEM_ADJUST();
+ }
+ else {
+ PACK_LENGTH_ADJUST_SIZE(sizeof(uint32_t));
+ while (len-- > 0) {
+ union {
+ uint32_t i;
+ char a[sizeof(uint32_t)];
+ } v;
+ memcpy(v.a, s, sizeof(uint32_t));
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap32(v.i);
+ s += sizeof(uint32_t);
+ rb_ary_push(ary, UINT2NUM(v.i));
+ }
+ PACK_ITEM_ADJUST();
+ }
+ break;
+#endif
- 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);
- rb_ary_push(ary, ULONG2NUM(ntohl(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
+#if defined(HAVE_INT64_T) && !defined(FORCE_BIG_PACK)
+ case SIZEOF_INT64_T:
+ if (signed_p) {
+ PACK_LENGTH_ADJUST_SIZE(sizeof(int64_t));
+ while (len-- > 0) {
+ union {
+ int64_t i;
+ char a[sizeof(int64_t)];
+ } v;
+ memcpy(v.a, s, sizeof(int64_t));
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
+ s += sizeof(int64_t);
+ rb_ary_push(ary, INT64toNUM(v.i));
+ }
+ PACK_ITEM_ADJUST();
+ }
+ else {
+ PACK_LENGTH_ADJUST_SIZE(sizeof(uint64_t));
+ while (len-- > 0) {
+ union {
+ uint64_t i;
+ char a[sizeof(uint64_t)];
+ } v;
+ memcpy(v.a, s, sizeof(uint64_t));
+ if (bigendian_p != BIGENDIAN_P()) v.i = swap64(v.i);
+ s += sizeof(uint64_t);
+ rb_ary_push(ary, UINT64toNUM(v.i));
+ }
+ PACK_ITEM_ADJUST();
+ }
+ break;
+#endif
- case 'v':
- 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);
- rb_ary_push(ary, UINT2NUM(vtohs(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
- case 'V':
- PACK_LENGTH_ADJUST(unsigned long,4);
- while (len-- > 0) {
- unsigned long tmp = 0;
- memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
- s += NATINT_LEN(long,4);
- rb_ary_push(ary, ULONG2NUM(vtohl(tmp)));
- }
- PACK_ITEM_ADJUST();
- break;
+ default:
+ if (integer_size > MAX_INTEGER_PACK_SIZE)
+ rb_bug("unexpected intger size for pack: %d", integer_size);
+ PACK_LENGTH_ADJUST_SIZE(integer_size);
+ while (len-- > 0) {
+ union {
+ unsigned long i[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG)/SIZEOF_LONG];
+ char a[(MAX_INTEGER_PACK_SIZE+SIZEOF_LONG)/SIZEOF_LONG*SIZEOF_LONG];
+ } v;
+ int num_longs = (integer_size+SIZEOF_LONG)/SIZEOF_LONG;
+ int i;
+
+ if (signed_p && (signed char)s[bigendian_p ? 0 : (integer_size-1)] < 0)
+ memset(v.a, 0xff, sizeof(long)*num_longs);
+ else
+ memset(v.a, 0, sizeof(long)*num_longs);
+ if (bigendian_p)
+ memcpy(v.a + sizeof(long)*num_longs - integer_size, s, integer_size);
+ else
+ memcpy(v.a, s, integer_size);
+ if (bigendian_p) {
+ for (i = 0; i < num_longs/2; i++) {
+ unsigned long t = v.i[i];
+ v.i[i] = v.i[num_longs-1-i];
+ v.i[num_longs-1-i] = t;
+ }
+ }
+ if (bigendian_p != BIGENDIAN_P()) {
+ for (i = 0; i < num_longs; i++)
+ v.i[i] = swapl(v.i[i]);
+ }
+ s += integer_size;
+ rb_ary_push(ary, rb_big_unpack(v.i, num_longs));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+ }
+ break;
case 'f':
case 'F':
- PACK_LENGTH_ADJUST(float,sizeof(float));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) {
float tmp;
memcpy(&tmp, s, sizeof(float));
@@ -1652,7 +1758,7 @@ pack_unpack(str, fmt)
break;
case 'e':
- PACK_LENGTH_ADJUST(float,sizeof(float));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) {
float tmp;
FLOAT_CONVWITH(ftmp);
@@ -1666,7 +1772,7 @@ pack_unpack(str, fmt)
break;
case 'E':
- PACK_LENGTH_ADJUST(double,sizeof(double));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) {
double tmp;
DOUBLE_CONVWITH(dtmp);
@@ -1681,7 +1787,7 @@ pack_unpack(str, fmt)
case 'D':
case 'd':
- PACK_LENGTH_ADJUST(double,sizeof(double));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) {
double tmp;
memcpy(&tmp, s, sizeof(double));
@@ -1692,7 +1798,7 @@ pack_unpack(str, fmt)
break;
case 'g':
- PACK_LENGTH_ADJUST(float,sizeof(float));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) {
float tmp;
FLOAT_CONVWITH(ftmp;)
@@ -1706,7 +1812,7 @@ pack_unpack(str, fmt)
break;
case 'G':
- PACK_LENGTH_ADJUST(double,sizeof(double));
+ PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) {
double tmp;
DOUBLE_CONVWITH(dtmp);
@@ -1886,7 +1992,7 @@ pack_unpack(str, fmt)
break;
case 'P':
- if (sizeof(char *) <= send - s) {
+ if (sizeof(char *) <= (size_t)(send - s)) {
VALUE tmp = Qnil;
char *t;
@@ -1926,7 +2032,7 @@ pack_unpack(str, fmt)
if (len > (send - s) / sizeof(char *))
len = (send - s) / sizeof(char *);
while (len-- > 0) {
- if (send - s < sizeof(char *))
+ if ((size_t)(send - s) < sizeof(char *))
break;
else {
VALUE tmp = Qnil;
diff --git a/ruby.h b/ruby.h
index f6e7ef478e..4129299757 100644
--- a/ruby.h
+++ b/ruby.h
@@ -50,6 +50,10 @@ extern "C" {
# include <intrinsics.h>
#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
#include <stddef.h>
#include <stdio.h>
diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb
index a8f0176879..bd5e1f2d19 100644
--- a/test/ruby/test_pack.rb
+++ b/test/ruby/test_pack.rb
@@ -20,6 +20,31 @@ class TestPack < Test::Unit::TestCase
assert_equal($x, $x.pack("l").unpack("l"))
end
+ def test_pack_n
+ assert_equal "\000\000", [0].pack('n')
+ assert_equal "\000\001", [1].pack('n')
+ assert_equal "\000\002", [2].pack('n')
+ assert_equal "\000\003", [3].pack('n')
+ assert_equal "\377\376", [65534].pack('n')
+ assert_equal "\377\377", [65535].pack('n')
+
+ assert_equal "\200\000", [2**15].pack('n')
+ assert_equal "\177\377", [-2**15-1].pack('n')
+ assert_equal "\377\377", [-1].pack('n')
+
+ assert_equal "\000\001\000\001", [1,1].pack('n*')
+ assert_equal "\000\001\000\001\000\001", [1,1,1].pack('n*')
+ end
+
+ def test_unpack_n
+ assert_equal 1, "\000\001".unpack('n')[0]
+ assert_equal 2, "\000\002".unpack('n')[0]
+ assert_equal 3, "\000\003".unpack('n')[0]
+ assert_equal 65535, "\377\377".unpack('n')[0]
+ assert_equal [1,1], "\000\001\000\001".unpack('n*')
+ assert_equal [1,1,1], "\000\001\000\001\000\001".unpack('n*')
+ end
+
def test_pack_N
assert_equal "\000\000\000\000", [0].pack('N')
assert_equal "\000\000\000\001", [1].pack('N')
@@ -40,22 +65,206 @@ class TestPack < Test::Unit::TestCase
assert_equal 1, "\000\000\000\001".unpack('N')[0]
assert_equal 2, "\000\000\000\002".unpack('N')[0]
assert_equal 3, "\000\000\000\003".unpack('N')[0]
- assert_equal 3, "\000\000\000\003".unpack('N')[0]
assert_equal 4294967295, "\377\377\377\377".unpack('N')[0]
assert_equal [1,1], "\000\000\000\001\000\000\000\001".unpack('N*')
assert_equal [1,1,1], "\000\000\000\001\000\000\000\001\000\000\000\001".unpack('N*')
end
+ def test_integer_endian
+ s = [1].pack("s")
+ assert_operator(["\0\1", "\1\0"], :include?, s)
+ if s == "\0\1"
+ # big endian
+ assert_equal("\x01\x02", [0x0102].pack("s"))
+ assert_equal("\x01\x02", [0x0102].pack("S"))
+ assert_equal("\x01\x02\x03\x04", [0x01020304].pack("l"))
+ assert_equal("\x01\x02\x03\x04", [0x01020304].pack("L"))
+ assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("q"))
+ assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("Q"))
+ assert_match(/\A\x00*\x01\x02\z/, [0x0102].pack("s!"))
+ assert_match(/\A\x00*\x01\x02\z/, [0x0102].pack("S!"))
+ assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("i"))
+ assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("I"))
+ assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("i!"))
+ assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("I!"))
+ assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("l!"))
+ assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("L!"))
+ %w[s S l L q Q s! S! i I i! I! l! L!].each {|fmt|
+ nuls = [0].pack(fmt)
+ v = 0
+ s = ""
+ nuls.bytesize.times {|i|
+ j = i + 40
+ v = v * 256 + j
+ s << [j].pack("C")
+ }
+ assert_equal(s, [v].pack(fmt), "[#{v}].pack(#{fmt.dump})")
+ assert_equal([v], s.unpack(fmt), "#{s.dump}.unpack(#{fmt.dump})")
+ s2 = s+s
+ fmt2 = fmt+"*"
+ assert_equal([v,v], s2.unpack(fmt2), "#{s2.dump}.unpack(#{fmt2.dump})")
+ }
+ else
+ # little endian
+ assert_equal("\x02\x01", [0x0102].pack("s"))
+ assert_equal("\x02\x01", [0x0102].pack("S"))
+ assert_equal("\x04\x03\x02\x01", [0x01020304].pack("l"))
+ assert_equal("\x04\x03\x02\x01", [0x01020304].pack("L"))
+ assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("q"))
+ assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("Q"))
+ assert_match(/\A\x02\x01\x00*\z/, [0x0102].pack("s!"))
+ assert_match(/\A\x02\x01\x00*\z/, [0x0102].pack("S!"))
+ assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("i"))
+ assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("I"))
+ assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("i!"))
+ assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("I!"))
+ assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("l!"))
+ assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("L!"))
+ %w[s S l L q Q s! S! i I i! I! l! L!].each {|fmt|
+ nuls = [0].pack(fmt)
+ v = 0
+ s = ""
+ nuls.bytesize.times {|i|
+ j = i+40
+ v = v * 256 + j
+ s << [j].pack("C")
+ }
+ s.reverse!
+ assert_equal(s, [v].pack(fmt), "[#{v}].pack(#{fmt.dump})")
+ assert_equal([v], s.unpack(fmt), "#{s.dump}.unpack(#{fmt.dump})")
+ s2 = s+s
+ fmt2 = fmt+"*"
+ assert_equal([v,v], s2.unpack(fmt2), "#{s2.dump}.unpack(#{fmt2.dump})")
+ }
+ end
+ end
+
def test_pack_U
- assert_raises(RangeError) { [-0x40000001].pack("U") }
- assert_raises(RangeError) { [-0x40000000].pack("U") }
- assert_raises(RangeError) { [-1].pack("U") }
+ assert_raise(RangeError) { [-0x40000001].pack("U") }
+ assert_raise(RangeError) { [-0x40000000].pack("U") }
+ assert_raise(RangeError) { [-1].pack("U") }
assert_equal "\000", [0].pack("U")
assert_equal "\374\277\277\277\277\277", [0x3fffffff].pack("U")
assert_equal "\375\200\200\200\200\200", [0x40000000].pack("U")
assert_equal "\375\277\277\277\277\277", [0x7fffffff].pack("U")
- assert_raises(RangeError) { [0x80000000].pack("U") }
- assert_raises(RangeError) { [0x100000000].pack("U") }
+ assert_raise(RangeError) { [0x80000000].pack("U") }
+ assert_raise(RangeError) { [0x100000000].pack("U") }
+ end
+
+ def test_pack_P
+ a = ["abc"]
+ assert_equal a, a.pack("P").unpack("P*")
+ assert_equal "a", a.pack("P").unpack("P")[0]
+ assert_equal a, a.pack("P").freeze.unpack("P*")
+ assert_raise(ArgumentError) { (a.pack("P") + "").unpack("P*") }
+ end
+
+ def test_pack_p
+ a = ["abc"]
+ assert_equal a, a.pack("p").unpack("p*")
+ assert_equal a[0], a.pack("p").unpack("p")[0]
+ assert_equal a, a.pack("p").freeze.unpack("p*")
+ assert_raise(ArgumentError) { (a.pack("p") + "").unpack("p*") }
+ end
+
+ def test_format_string_modified
+ fmt = "CC"
+ o = Object.new
+ class << o; self; end.class_eval do
+ define_method(:to_int) { fmt.replace ""; 0 }
+ end
+ assert_raise(RuntimeError) do
+ [o, o].pack(fmt)
+ end
+ end
+
+ def test_comment
+ assert_equal("\0\1", [0,1].pack(" C #foo \n C "))
+ assert_equal([0,1], "\0\1".unpack(" C #foo \n C "))
+ end
+
+ def test_illegal_bang
+ assert_raise(ArgumentError) { [].pack("a!") }
+ assert_raise(ArgumentError) { "".unpack("a!") }
+ end
+
+ def test_pack_unpack_aA
+ assert_equal("f", ["foo"].pack("A"))
+ assert_equal("f", ["foo"].pack("a"))
+ assert_equal("foo", ["foo"].pack("A*"))
+ assert_equal("foo", ["foo"].pack("a*"))
+ assert_equal("fo", ["foo"].pack("A2"))
+ assert_equal("fo", ["foo"].pack("a2"))
+ assert_equal("foo ", ["foo"].pack("A4"))
+ assert_equal("foo\0", ["foo"].pack("a4"))
+ assert_equal(" ", [nil].pack("A"))
+ assert_equal("\0", [nil].pack("a"))
+ assert_equal("", [nil].pack("A*"))
+ assert_equal("", [nil].pack("a*"))
+ assert_equal(" ", [nil].pack("A2"))
+ assert_equal("\0\0", [nil].pack("a2"))
+
+ assert_equal("foo" + "\0" * 27, ["foo"].pack("a30"))
+
+ assert_equal(["f"], "foo\0".unpack("A"))
+ assert_equal(["f"], "foo\0".unpack("a"))
+ assert_equal(["foo"], "foo\0".unpack("A4"))
+ assert_equal(["foo\0"], "foo\0".unpack("a4"))
+ assert_equal(["foo"], "foo ".unpack("A4"))
+ assert_equal(["foo "], "foo ".unpack("a4"))
+ assert_equal(["foo"], "foo".unpack("A4"))
+ assert_equal(["foo"], "foo".unpack("a4"))
+ end
+
+ def test_pack_unpack_Z
+ assert_equal("f", ["foo"].pack("Z"))
+ assert_equal("foo\0", ["foo"].pack("Z*"))
+ assert_equal("fo", ["foo"].pack("Z2"))
+ assert_equal("foo\0\0", ["foo"].pack("Z5"))
+ assert_equal("\0", [nil].pack("Z"))
+ assert_equal("\0", [nil].pack("Z*"))
+ assert_equal("\0\0", [nil].pack("Z2"))
+
+ assert_equal(["f"], "foo\0".unpack("Z"))
+ assert_equal(["foo"], "foo".unpack("Z*"))
+ assert_equal(["foo"], "foo\0".unpack("Z*"))
+ assert_equal(["foo"], "foo".unpack("Z5"))
+ end
+
+ def test_pack_unpack_bB
+ assert_equal("\xff\x00", ["1111111100000000"].pack("b*"))
+ assert_equal("\x01\x02", ["1000000001000000"].pack("b*"))
+ assert_equal("", ["1"].pack("b0"))
+ assert_equal("\x01", ["1"].pack("b1"))
+ assert_equal("\x01\x00", ["1"].pack("b2"))
+ assert_equal("\x01\x00", ["1"].pack("b3"))
+ assert_equal("\x01\x00\x00", ["1"].pack("b4"))
+ assert_equal("\x01\x00\x00", ["1"].pack("b5"))
+ assert_equal("\x01\x00\x00\x00", ["1"].pack("b6"))
+
+ assert_equal("\xff\x00", ["1111111100000000"].pack("B*"))
+ assert_equal("\x01\x02", ["0000000100000010"].pack("B*"))
+ assert_equal("", ["1"].pack("B0"))
+ assert_equal("\x80", ["1"].pack("B1"))
+ assert_equal("\x80\x00", ["1"].pack("B2"))
+ assert_equal("\x80\x00", ["1"].pack("B3"))
+ assert_equal("\x80\x00\x00", ["1"].pack("B4"))
+ assert_equal("\x80\x00\x00", ["1"].pack("B5"))
+ assert_equal("\x80\x00\x00\x00", ["1"].pack("B6"))
+
+ assert_equal(["1111111100000000"], "\xff\x00".unpack("b*"))
+ assert_equal(["1000000001000000"], "\x01\x02".unpack("b*"))
+ assert_equal([""], "".unpack("b0"))
+ assert_equal(["1"], "\x01".unpack("b1"))
+ assert_equal(["10"], "\x01".unpack("b2"))
+ assert_equal(["100"], "\x01".unpack("b3"))
+
+ assert_equal(["1111111100000000"], "\xff\x00".unpack("B*"))
+ assert_equal(["0000000100000010"], "\x01\x02".unpack("B*"))
+ assert_equal([""], "".unpack("B0"))
+ assert_equal(["1"], "\x80".unpack("B1"))
+ assert_equal(["10"], "\x80".unpack("B2"))
+ assert_equal(["100"], "\x80".unpack("B3"))
end
def test_pack_unpack_hH
diff --git a/version.h b/version.h
index 3b0e305283..2aee616c2c 100644
--- a/version.h
+++ b/version.h
@@ -2,7 +2,7 @@
#define RUBY_RELEASE_DATE "2010-06-08"
#define RUBY_VERSION_CODE 187
#define RUBY_RELEASE_CODE 20100608
-#define RUBY_PATCHLEVEL 284
+#define RUBY_PATCHLEVEL 285
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8