|
@@ -130,17 +130,17 @@ READ_POP_PUSH(int64, Int64)
|
|
|
READ_POP_PUSH(float, Float)
|
|
|
POP_PUSH(bool, Bool)
|
|
|
|
|
|
-static bool sPopPointer(Script* sc, Pointer* value) {
|
|
|
+bool sPopPointer(Script* sc, Pointer* value) {
|
|
|
return sPop(sc, value, sizeof(Pointer));
|
|
|
}
|
|
|
|
|
|
-static bool sPushPointer(Script* sc, Pointer* value) {
|
|
|
+bool sPushPointer(Script* sc, Pointer* value) {
|
|
|
return sPush(sc, value, sizeof(Pointer));
|
|
|
}
|
|
|
|
|
|
-static void sPushNullPointer(Script* sc) {
|
|
|
+bool sPushNullPointer(Script* sc) {
|
|
|
Pointer p = {-1, -1};
|
|
|
- sPushPointer(sc, &p);
|
|
|
+ return sPushPointer(sc, &p);
|
|
|
}
|
|
|
|
|
|
#define INVERT_SIGN(type, Type) \
|
|
@@ -162,7 +162,39 @@ static void sReserveBytes(Script* sc) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void* sCheckAddress(Script* sc, Pointer* p, int length) {
|
|
|
+static int32 sGetTextLength(Script* sc, Pointer* p) {
|
|
|
+ const int SIZE = sizeof(int32);
|
|
|
+ int sizeAddress = -p->array;
|
|
|
+ if(sizeAddress < 0 || sizeAddress + SIZE >= sc->code->length) {
|
|
|
+ sError(sc, "invalid code array length address %d", sizeAddress);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ int32 size;
|
|
|
+ memcpy(&size, sc->code->code + sizeAddress, SIZE);
|
|
|
+ return size;
|
|
|
+}
|
|
|
+
|
|
|
+static void* sCheckTextAddress(Script* sc, Pointer* p, int length) {
|
|
|
+ const int SIZE = sizeof(int32);
|
|
|
+ int address = p->offset + SIZE;
|
|
|
+ if(address + length > sc->code->length) {
|
|
|
+ sError(sc, "address %d is out of code bounds", address);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ int32 size = sGetTextLength(sc, p);
|
|
|
+ if(size == -1) {
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ int startAddress = -p->array + SIZE;
|
|
|
+ int endAddress = startAddress + size * SIZE;
|
|
|
+ if(address + length > endAddress || address < startAddress) {
|
|
|
+ sError(sc, "invalid text address %d", (address - startAddress) / SIZE);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ return sc->code->code + address;
|
|
|
+}
|
|
|
+
|
|
|
+void* sCheckAddress(Script* sc, Pointer* p, int length) {
|
|
|
if(p->array >= 0) {
|
|
|
Array* a = asGet(&sc->arrays, p->array);
|
|
|
if(a == NULL) {
|
|
@@ -173,12 +205,14 @@ static void* sCheckAddress(Script* sc, Pointer* p, int length) {
|
|
|
return NULL;
|
|
|
}
|
|
|
return ((char*)a->data) + p->offset;
|
|
|
+ } else if(p->array == -1) {
|
|
|
+ if(p->offset < 0 || p->offset + length > sc->stackIndex) {
|
|
|
+ sError(sc, "address %d is out of stack bounds", p->offset);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+ return sc->stack + p->offset;
|
|
|
}
|
|
|
- if(p->offset < 0 || p->offset + length > sc->stackIndex) {
|
|
|
- sError(sc, "address %d is out of stack bounds", p->offset);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- return sc->stack + p->offset;
|
|
|
+ return sCheckTextAddress(sc, p, length);
|
|
|
}
|
|
|
|
|
|
static void sNot(Script* sc) {
|
|
@@ -313,19 +347,32 @@ static void sDeleteArray(Script* sc) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+bool sGetPointerLength(Script* sc, Pointer* p, int32* length) {
|
|
|
+ if(p->array == -1) {
|
|
|
+ *length = p->offset >= 0;
|
|
|
+ return false;
|
|
|
+ } else if(p->array <= -1) {
|
|
|
+ int32 l = sGetTextLength(sc, p);
|
|
|
+ if(l != -1) {
|
|
|
+ *length = l;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ Array* a = asGet(&sc->arrays, p->array);
|
|
|
+ if(a == NULL) {
|
|
|
+ sError(sc, "invalid heap pointer %d", p->array);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ *length = a->length;
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static void sLength(Script* sc) {
|
|
|
Pointer p;
|
|
|
- if(sPopPointer(sc, &p)) {
|
|
|
- if(p.array == -1) {
|
|
|
- sPushInt32(sc, p.offset >= 0);
|
|
|
- return;
|
|
|
- }
|
|
|
- Array* a = asGet(&sc->arrays, p.array);
|
|
|
- if(a == NULL) {
|
|
|
- sError(sc, "invalid heap pointer");
|
|
|
- return;
|
|
|
- }
|
|
|
- sPushInt32(sc, a->length);
|
|
|
+ int32 length;
|
|
|
+ if(sPopPointer(sc, &p) && !sGetPointerLength(sc, &p, &length)) {
|
|
|
+ sPushInt32(sc, length);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -405,6 +452,16 @@ static void sCall(Script* sc) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void sPushText(Script* sc) {
|
|
|
+ int address = sc->readIndex;
|
|
|
+ int32 length;
|
|
|
+ if(sReadInt32(sc, &length)) {
|
|
|
+ Pointer p = {.array = -address, .offset = address};
|
|
|
+ sPushPointer(sc, &p);
|
|
|
+ sc->readIndex += sizeof(int32) * length;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
#define CHANGE_OP(type, op) \
|
|
|
{ \
|
|
|
char c = 0; \
|
|
@@ -497,6 +554,7 @@ static void sConsumeInstruction(Script* sc) {
|
|
|
case OP_PUSH_TRUE: sPushBool(sc, true); break;
|
|
|
case OP_PUSH_FALSE: sPushBool(sc, false); break;
|
|
|
case OP_PUSH_NULLPTR: sPushNullPointer(sc); break;
|
|
|
+ case OP_PUSH_TEXT: sPushText(sc); break;
|
|
|
case OP_DIV_INT32: DIVISION(int32, Int32); break;
|
|
|
case OP_DIV_INT64: DIVISION(int64, Int64); break;
|
|
|
case OP_DIV_FLOAT: DIVISION(float, Float); break;
|