summaryrefslogtreecommitdiffstats
path: root/generic/tclBinary.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclBinary.c')
-rw-r--r--generic/tclBinary.c72
1 files changed, 62 insertions, 10 deletions
diff --git a/generic/tclBinary.c b/generic/tclBinary.c
index c20f4df..d3b370c 100644
--- a/generic/tclBinary.c
+++ b/generic/tclBinary.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBinary.c,v 1.27 2005/11/04 22:38:38 msofer Exp $
+ * RCS: @(#) $Id: tclBinary.c,v 1.28 2006/04/26 13:42:43 dgp Exp $
*/
#include "tclInt.h"
@@ -1413,7 +1413,8 @@ GetFormatSpec(
*
* NeedReversing --
*
- * This routine determines, if bytes of a number need to be reversed.
+ * This routine determines, if bytes of a number need to be re-ordered,
+ * and returns a numeric code indicating the re-ordering to be done.
* This depends on the endiannes of the machine and the desired format.
* It is in effect a table (whose contents depend on the endianness of
* the system) describing whether a value needs reversing or not. Anyone
@@ -1423,7 +1424,10 @@ GetFormatSpec(
* Windows) don't need to do anything.
*
* Results:
- * 1 if reversion is required, 0 if not.
+ * 0 No re-ordering needed.
+ * 1 Reverse the bytes: 01234567 <-> 76543210 (little to big)
+ * 2 Apply this re-ordering: 01234567 <-> 45670123 (Nokia to little)
+ * 3 Apply this re-ordering: 01234567 <-> 32107654 (Nokia to big)
*
* Side effects:
* None
@@ -1448,12 +1452,11 @@ NeedReversing(
case 'n':
case 't':
case 'm':
- /* f+d: reverse if we're little-endian */
+ /* f: reverse if we're little-endian */
case 'Q':
case 'R':
#else /* !WORDS_BIGENDIAN */
/* small endian floats: reverse if we're big-endian */
- case 'q':
case 'r':
#endif /* WORDS_BIGENDIAN */
return 0;
@@ -1467,8 +1470,7 @@ NeedReversing(
case 'n':
case 't':
case 'm':
- /* f+d: reverse if we're little-endian */
- case 'Q':
+ /* f: reverse if we're little-endian */
case 'R':
#endif /* WORDS_BIGENDIAN */
/* small endian ints: always reverse */
@@ -1476,6 +1478,24 @@ NeedReversing(
case 's':
case 'w':
return 1;
+
+#ifndef WORDS_BIGENDIAN
+ /*
+ * The Q and q formats need special handling to account for the
+ * unusual byte ordering of 8-byte floats on Nokia 770 systems, which
+ * claim to be little-endian, but also reverse word order.
+ */
+ case 'Q':
+ if (TclNokia770Doubles()) {
+ return 3;
+ }
+ return 1;
+ case 'q':
+ if (TclNokia770Doubles()) {
+ return 2;
+ }
+ return 0;
+#endif
}
Tcl_Panic("unexpected fall-through");
@@ -1508,7 +1528,11 @@ CopyNumber(
unsigned int length, /* Number of bytes to copy */
int type) /* What type of thing are we copying? */
{
- if (NeedReversing(type)) {
+ switch (NeedReversing(type)) {
+ case 0:
+ memcpy(to, from, length);
+ break;
+ case 1: {
CONST unsigned char *fromPtr = (CONST unsigned char *) from;
unsigned char *toPtr = (unsigned char *) to;
@@ -1530,8 +1554,36 @@ CopyNumber(
toPtr[7] = fromPtr[0];
break;
}
- } else {
- memcpy(to, from, length);
+ break;
+ }
+ case 2: {
+ CONST unsigned char *fromPtr = (CONST unsigned char *) from;
+ unsigned char *toPtr = (unsigned char *) to;
+
+ toPtr[0] = fromPtr[4];
+ toPtr[1] = fromPtr[5];
+ toPtr[2] = fromPtr[6];
+ toPtr[3] = fromPtr[7];
+ toPtr[4] = fromPtr[0];
+ toPtr[5] = fromPtr[1];
+ toPtr[6] = fromPtr[2];
+ toPtr[7] = fromPtr[3];
+ break;
+ }
+ case 3: {
+ CONST unsigned char *fromPtr = (CONST unsigned char *) from;
+ unsigned char *toPtr = (unsigned char *) to;
+
+ toPtr[0] = fromPtr[3];
+ toPtr[1] = fromPtr[2];
+ toPtr[2] = fromPtr[1];
+ toPtr[3] = fromPtr[0];
+ toPtr[4] = fromPtr[7];
+ toPtr[5] = fromPtr[6];
+ toPtr[6] = fromPtr[5];
+ toPtr[7] = fromPtr[4];
+ break;
+ }
}
}