summaryrefslogtreecommitdiff
path: root/pack.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-05-23 06:16:20 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-05-23 06:16:20 +0000
commit228604473da9819e031ea2b48017f9246d1dbd48 (patch)
tree7d717cb465bafaefda8c17c790da103ce94209dc /pack.c
parent2e4ffa7a447f94f2aaa44c206db845da029be484 (diff)
* pack.c (pack_unpack): sign-extend if sizeof long is bigger than
32. (ruby-bugs-ja:PR#472) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3858 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'pack.c')
-rw-r--r--pack.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/pack.c b/pack.c
index 58aa5d4105..b0b51c1b2a 100644
--- a/pack.c
+++ b/pack.c
@@ -351,6 +351,18 @@ num2u32(x)
# endif
#endif
+#if SIZEOF_LONG == SIZE32 || SIZEOF_INT == SIZE32
+# define EXTEND32(x) ((I32)(x))
+#else
+/* invariant in modulo 1<<31 */
+# define EXTEND32(x) (I32)(((1<<31)-1-(x))^~(~0<<31))
+#endif
+#if SIZEOF_SHORT == SIZE16
+# define EXTEND16(x) (short)(x)
+#else
+# define EXTEND16(x) (short)(((1<<15)-1-(x))^~(~0<<15))
+#endif
+
#ifdef HAVE_LONG_LONG
# define QUAD_SIZE sizeof(LONG_LONG)
#else
@@ -1317,6 +1329,9 @@ pack_unpack(str, fmt)
while (len-- > 0) {
short tmp = 0;
memcpy(OFF16(&tmp), s, NATINT_LEN(short,2));
+#if SIZEOF_SHORT != SIZE16
+ if (!natint) tmp = EXTEND16(tmp);
+#endif
s += NATINT_LEN(short,2);
rb_ary_push(ary, INT2FIX(tmp));
}
@@ -1361,6 +1376,9 @@ pack_unpack(str, fmt)
while (len-- > 0) {
long tmp = 0;
memcpy(OFF32(&tmp), s, NATINT_LEN(long,4));
+#if SIZEOF_LONG != SIZE32
+ if (!natint) tmp = EXTEND32(tmp);
+#endif
s += NATINT_LEN(long,4);
rb_ary_push(ary, LONG2NUM(tmp));
}