mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 23:04:08 +10:00
Added loadScriptBytecode()
This commit is contained in:
@@ -75,6 +75,13 @@ static int nativeLoadScript(Interpreter* interpreter, LiteralArray* arguments) {
|
|||||||
deleteRefString(drivePath);
|
deleteRefString(drivePath);
|
||||||
freeLiteral(drivePathLiteral);
|
freeLiteral(drivePathLiteral);
|
||||||
|
|
||||||
|
//check for file extensions
|
||||||
|
if (!(filePath[realLength - 5] == '.' && filePath[realLength - 4] == 't' && filePath[realLength - 3] == 'o' && filePath[realLength - 2] == 'y')) {
|
||||||
|
interpreter->errorOutput("Bad script file extension (expected .toy)\n");
|
||||||
|
FREE_ARRAY(char, filePath, realLength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
//check for break-out attempts
|
//check for break-out attempts
|
||||||
for (int i = 0; i < realLength - 1; i++) {
|
for (int i = 0; i < realLength - 1; i++) {
|
||||||
if (filePath[i] == '.' && filePath[i + 1] == '.') {
|
if (filePath[i] == '.' && filePath[i + 1] == '.') {
|
||||||
@@ -122,6 +129,110 @@ static int nativeLoadScript(Interpreter* interpreter, LiteralArray* arguments) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nativeLoadScriptBytecode(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
|
//arguments
|
||||||
|
if (arguments->count != 1) {
|
||||||
|
interpreter->errorOutput("Incorrect number of arguments to loadScriptBytecode\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the argument
|
||||||
|
Literal drivePathLiteral = popLiteralArray(arguments);
|
||||||
|
RefString* drivePath = copyRefString(AS_STRING(drivePathLiteral));
|
||||||
|
|
||||||
|
//get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library
|
||||||
|
int driveLength = 0;
|
||||||
|
while (toCString(drivePath)[driveLength] != ':') {
|
||||||
|
if (driveLength >= lengthRefString(drivePath)) {
|
||||||
|
interpreter->errorOutput("Incorrect drive path format given to loadScriptBytecode\n");
|
||||||
|
deleteRefString(drivePath);
|
||||||
|
freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
driveLength++;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefString* drive = createRefStringLength(toCString(drivePath), driveLength);
|
||||||
|
RefString* path = createRefStringLength( &toCString(drivePath)[driveLength + 1], lengthRefString(drivePath) - driveLength );
|
||||||
|
|
||||||
|
//get the real drive file path
|
||||||
|
Literal driveLiteral = TO_STRING_LITERAL(drive); //NOTE: driveLiteral takes ownership of the refString
|
||||||
|
Literal realDriveLiteral = getLiteralDictionary(getDriveDictionary(), driveLiteral);
|
||||||
|
|
||||||
|
if (!IS_STRING(realDriveLiteral)) {
|
||||||
|
interpreter->errorOutput("Incorrect literal type found for drive: ");
|
||||||
|
printLiteralCustom(realDriveLiteral, interpreter->errorOutput);
|
||||||
|
interpreter->errorOutput("\n");
|
||||||
|
freeLiteral(realDriveLiteral);
|
||||||
|
freeLiteral(driveLiteral);
|
||||||
|
deleteRefString(path);
|
||||||
|
deleteRefString(drivePath);
|
||||||
|
freeLiteral(drivePathLiteral);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the final real file path (concat) TODO: move this concat to refstring library
|
||||||
|
RefString* realDrive = copyRefString(AS_STRING(realDriveLiteral));
|
||||||
|
int realLength = lengthRefString(realDrive) + lengthRefString(path);
|
||||||
|
|
||||||
|
char* filePath = ALLOCATE(char, realLength + 1); //+1 for null
|
||||||
|
snprintf(filePath, realLength, "%s%s", toCString(realDrive), toCString(path));
|
||||||
|
|
||||||
|
//clean up the drivepath stuff
|
||||||
|
deleteRefString(realDrive);
|
||||||
|
freeLiteral(realDriveLiteral);
|
||||||
|
freeLiteral(driveLiteral);
|
||||||
|
deleteRefString(path);
|
||||||
|
deleteRefString(drivePath);
|
||||||
|
freeLiteral(drivePathLiteral);
|
||||||
|
|
||||||
|
//check for file extensions
|
||||||
|
if (!(filePath[realLength - 4] == '.' && filePath[realLength - 3] == 't' && filePath[realLength - 2] == 'b')) {
|
||||||
|
interpreter->errorOutput("Bad binary file extension (expected .tb)\n");
|
||||||
|
FREE_ARRAY(char, filePath, realLength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//check for break-out attempts
|
||||||
|
for (int i = 0; i < realLength - 1; i++) {
|
||||||
|
if (filePath[i] == '.' && filePath[i + 1] == '.') {
|
||||||
|
interpreter->errorOutput("Parent directory access not allowed\n");
|
||||||
|
FREE_ARRAY(char, filePath, realLength);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//load the bytecode
|
||||||
|
size_t fileSize = 0;
|
||||||
|
unsigned char* bytecode = (unsigned char*)readFile(filePath, &fileSize);
|
||||||
|
|
||||||
|
if (!bytecode) {
|
||||||
|
interpreter->errorOutput("Failed to load bytecode file\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//build the runner object
|
||||||
|
Runner* runner = ALLOCATE(Runner, 1);
|
||||||
|
setInterpreterPrint(&runner->interpreter, interpreter->printOutput);
|
||||||
|
setInterpreterAssert(&runner->interpreter, interpreter->assertOutput);
|
||||||
|
setInterpreterError(&runner->interpreter, interpreter->errorOutput);
|
||||||
|
runner->interpreter.hooks = interpreter->hooks;
|
||||||
|
runner->interpreter.scope = NULL;
|
||||||
|
resetInterpreter(&runner->interpreter);
|
||||||
|
runner->bytecode = bytecode;
|
||||||
|
runner->size = fileSize;
|
||||||
|
runner->dirty = false;
|
||||||
|
|
||||||
|
//build the opaque object, and push it to the stack
|
||||||
|
Literal runnerLiteral = TO_OPAQUE_LITERAL(runner, OPAQUE_TAG_RUNNER);
|
||||||
|
pushLiteralArray(&interpreter->stack, runnerLiteral);
|
||||||
|
|
||||||
|
FREE_ARRAY(char, filePath, realLength);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int nativeRunScript(Interpreter* interpreter, LiteralArray* arguments) {
|
static int nativeRunScript(Interpreter* interpreter, LiteralArray* arguments) {
|
||||||
//no arguments
|
//no arguments
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
@@ -432,6 +543,7 @@ int hookRunner(Interpreter* interpreter, Literal identifier, Literal alias) {
|
|||||||
//build the natives list
|
//build the natives list
|
||||||
Natives natives[] = {
|
Natives natives[] = {
|
||||||
{"loadScript", nativeLoadScript},
|
{"loadScript", nativeLoadScript},
|
||||||
|
{"loadScriptBytecode", nativeLoadScriptBytecode},
|
||||||
{"_runScript", nativeRunScript},
|
{"_runScript", nativeRunScript},
|
||||||
{"_getScriptVar", nativeGetScriptVar},
|
{"_getScriptVar", nativeGetScriptVar},
|
||||||
{"_callScriptFn", nativeCallScriptFn},
|
{"_callScriptFn", nativeCallScriptFn},
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
import runner;
|
import runner;
|
||||||
|
|
||||||
//test basic loading and freeing of code
|
//test basic loading and freeing of a script file
|
||||||
{
|
{
|
||||||
var s = loadScript("scripts:/runner_sample_code.toy");
|
var s = loadScript("scripts:/runner_sample_code.toy");
|
||||||
|
|
||||||
s.freeScript();
|
s.freeScript();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//test basic loading and freeing of a binary file
|
||||||
|
{
|
||||||
|
var s = loadScriptBytecode("scripts:/lib/runner/sample_bytecode.tb");
|
||||||
|
|
||||||
|
s.freeScript();
|
||||||
|
}
|
||||||
|
|
||||||
//test running an external script
|
//test running an external script
|
||||||
{
|
{
|
||||||
var s = loadScript("scripts:/runner_sample_code.toy");
|
var s = loadScript("scripts:/runner_sample_code.toy");
|
||||||
|
|||||||
BIN
test/scripts/lib/runner/sample_bytecode.tb
Normal file
BIN
test/scripts/lib/runner/sample_bytecode.tb
Normal file
Binary file not shown.
Reference in New Issue
Block a user