UninterpretedBytes.st
changeset 22883 711de6b11ff1
parent 22504 00b1dfdd05b4
child 23626 a08a4299109d
--- a/UninterpretedBytes.st	Thu May 10 21:05:57 2018 +0200
+++ b/UninterpretedBytes.st	Thu May 10 21:26:56 2018 +0200
@@ -3494,51 +3494,48 @@
     "get a pointer starting at byteIndex as ExternalAddress.
      The byteIndex is a smalltalk index (i.e. 1-based).
      Only aligned accesses are allowed.
-     The pointer is of native cpu's size (4 or 8 bytes)"
+     The pointer is of native cpu's size (4 or 8 bytes).
+     This returns an external adress."
+
+    |failReason|
 
 %{
     if (__isSmallInteger(byteIndex)) {
-	unsigned char *cp;
-	INT sz;
-
-	__fetchBytePointerAndSize__(self, &cp, &sz);
-	if (cp) {
-	    INT idx = __smallIntegerVal(byteIndex) - 1;
-	    char *pointer;
-
-	    if ((idx >= 0) && ((idx+(sizeof(pointer)-1)) < sz)) {
-		cp += idx;
-		/*
-		 * aligned
-		 */
-		if (((INT)cp & (sizeof(pointer)-1)) == 0) {
-		    pointer = ((char **)cp)[0];
-		    RETURN (__MKEXTERNALADDRESS(pointer));
-		} else {
-#if 0
-		    printf("cp UNALIGNED (%"_lx_")\n", (INT)cp);
-#endif
-		}
-	    } else {
-#if 0
-		printf("idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n",
-			idx, (int)(sizeof(pointer)-1), sz);
-#endif
-	    }
-	} else {
-#if 0
-	    printf("cp is NULL\n");
-#endif
-	}
+        unsigned char *cp;
+        INT sz;
+
+        __fetchBytePointerAndSize__(self, &cp, &sz);
+        if (cp) {
+            INT idx = __smallIntegerVal(byteIndex) - 1;
+            char *pointer;
+
+            if ((idx >= 0) && ((idx+(sizeof(pointer)-1)) < sz)) {
+                cp += idx;
+                /*
+                 * aligned
+                 */
+                if (((INT)cp & (sizeof(pointer)-1)) == 0) {
+                    pointer = ((char **)cp)[0];
+                    RETURN (__MKEXTERNALADDRESS(pointer));
+                }
+                // fprintf(stderr, "cp UNALIGNED (%"_lx_")\n", (INT)cp);
+                failReason = @symbol(unaligned);
+            } else {
+                // fprintf(stderr, "idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n",
+                //        idx, (int)(sizeof(pointer)-1), sz);
+                failReason = @symbol(invalidIndex);
+            }
+        } else {
+            // fprintf(stderr, "cp is NULL\n");
+            failReason = @symbol(nullPointer);
+        }
     } else {
-#if 0
-	printf("bad index\n");
-#endif
+        // fprintf(stderr, "non integer index\n");
+        failReason = @symbol(invalidIndex);
     }
 bad:;
 %}.
-
-    self primitiveFailed.
+    ^ self reportError:failReason with:byteIndex
 
     "
      |b|
@@ -3564,49 +3561,63 @@
      The pointer is of native cpu's size (4 or 8 bytes).
      The value may be either an ExternalAddress, ExternalBytes or an Integer"
 
+    |failReason|
+
 %{
     OBJ *pointer;
 
     if (__isExternalAddressLike(value)) {
-	pointer = __externalAddressVal(value);
+        pointer = __externalAddressVal(value);
     } else if (__isExternalBytesLike(value)) {
-	pointer = __externalBytesVal(value);
-	if (pointer == (OBJ *)0)
-	    pointer = 0;
+        pointer = __externalBytesVal(value);
+        if (pointer == (OBJ *)0)
+            pointer = 0;
     } else if (value == nil) {
-	pointer = 0;
+        pointer = 0;
     } else if (__isSmallInteger(value)) {
-	pointer = (OBJ *)__intVal(value);
+        pointer = (OBJ *)__intVal(value);
     } else {
-	if ((pointer = (OBJ *)__unsignedLongIntVal(value)) == 0) {
-	    goto bad;
-	}
+        if ((pointer = (OBJ *)__unsignedLongIntVal(value)) == 0) {
+            // fprintf(stderr, "not a largeInt\n");
+            failReason = @symbol(badValue);
+            goto bad;
+        }
     }
 
     if (__isSmallInteger(byteIndex)) {
-	unsigned char *cp;
-	INT sz;
-
-	__fetchBytePointerAndSize__(self, &cp, &sz);
-	if (cp) {
-	    INT idx = __smallIntegerVal(byteIndex) - 1;
-
-	    if ((idx >= 0) && ((idx+(sizeof(pointer)-1)) < sz)) {
-		cp += idx;
-		/*
-		 * aligned
-		 */
-		if (((INT)cp & (sizeof(pointer)-1)) == 0) {
-		    ((char **)cp)[0] = (char *) pointer;
-		    RETURN (value);
-		}
-	    }
-	}
+        unsigned char *cp;
+        INT sz;
+
+        __fetchBytePointerAndSize__(self, &cp, &sz);
+        if (cp) {
+            INT idx = __smallIntegerVal(byteIndex) - 1;
+
+            if ((idx >= 0) && ((idx+(sizeof(pointer)-1)) < sz)) {
+                cp += idx;
+                /*
+                 * aligned
+                 */
+                if (((INT)cp & (sizeof(pointer)-1)) == 0) {
+                    ((char **)cp)[0] = (char *) pointer;
+                    RETURN (value);
+                }
+                // fprintf(stderr, "cp unaligned\n");
+                failReason = @symbol(unaligned);
+            } else {
+                // fprintf(stderr, "idx out of bounds\n");
+                failReason = @symbol(invalidIndex);
+            }
+        } else {
+            // fprintf(stderr, "cp is null\n");
+            failReason = @symbol(nullPointer);
+        }
+    } else {
+        // fprintf(stderr, "byteIndex not a smallInt\n");
+        failReason = @symbol(invalidIndex);
     }
 bad:;
 %}.
-
-    self primitiveFailed.
+    ^ self reportError:failReason with:byteIndex
 
     "
      |b|
@@ -3626,41 +3637,45 @@
      The pointer is of native cpu's size (4 or 8 bytes).
      This returns an int with sizeof the machines's native pointer (4 or 8 bytes)"
 
+    |failReason|
 %{
     if (__isSmallInteger(byteIndex)) {
-	unsigned char *cp;
-	INT sz;
-
-	__fetchBytePointerAndSize__(self, &cp, &sz);
-	if (cp) {
-	    INT idx = __smallIntegerVal(byteIndex) - 1;
-	    char *pointer;
-
-	    if ((idx >= 0) && ((idx+(sizeof(pointer)-1)) < sz)) {
-		cp += idx;
-		/*
-		 * aligned
-		 */
-		if (((INT)cp & (sizeof(pointer)-1)) == 0) {
-		    pointer = ((char **)cp)[0];
-		    RETURN (__MKUINT((INT)(pointer)));
-		} else {
-		    // printf("cp UNALIGNED (%"_lx_")\n", (INT)cp);
-		}
-	    } else {
-		// printf("idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n",
-		//        idx, (int)(sizeof(pointer)-1), sz);
-	    }
-	} else {
-	    // printf("cp is NULL\n");
-	}
+        unsigned char *cp;
+        INT sz;
+
+        __fetchBytePointerAndSize__(self, &cp, &sz);
+        if (cp) {
+            INT idx = __smallIntegerVal(byteIndex) - 1;
+            char *pointer;
+
+            if ((idx >= 0) && ((idx+(sizeof(pointer)-1)) < sz)) {
+                cp += idx;
+                /*
+                 * aligned
+                 */
+                if (((INT)cp & (sizeof(pointer)-1)) == 0) {
+                    pointer = ((char **)cp)[0];
+                    RETURN (__MKUINT((INT)(pointer)));
+                }
+                // printf("cp UNALIGNED (%"_lx_")\n", (INT)cp);
+                failReason = @symbol(unaligned);
+            } else {
+                // printf("idx(%"_ld_")+(sizeof(pointer)-1) (%d) >= sz (%"_ld_")\n",
+                //        idx, (int)(sizeof(pointer)-1), sz);
+                failReason = @symbol(invalidIndex);
+            }
+        } else {
+            // fprintf(stderr, "cp is NULL\n");
+            failReason = @symbol(nullPointer);
+        }
     } else {
-	// printf("bad index\n");
+        // fprintf(stderr, "non integer index\n");
+        failReason = @symbol(invalidIndex);
     }
 bad:;
 %}.
 
-    self primitiveFailed.
+    ^ self reportError:failReason with:byteIndex
 
     "
      |b|
@@ -5029,6 +5044,21 @@
 
 !UninterpretedBytes methodsFor:'private'!
 
+reportError:failReason with:parameter
+    "common helper"
+
+    (failReason == #invalidIndex) ifTrue:[
+        ^ self indexNotIntegerOrOutOfBounds:parameter
+    ].
+    failReason == #nullPointer ifTrue:[
+        ^ self error:'free or unallocated object referenced'
+    ].
+    failReason == #unaligned ifTrue:[
+        ^ self error:'unaligned index'. 
+    ].
+    self primitiveFailed:failReason.
+!
+
 slowReplaceBytesFrom:startArg to:stopArg with:sourceBytes startingAt:sourceIndex
     "fallback if primitive code fails"