From e2fa1cf2e86988605c1e104bfab533b0a86f2be4 Mon Sep 17 00:00:00 2001 From: Kayne Ruse Date: Wed, 15 Mar 2023 06:12:35 +1100 Subject: [PATCH] Moved lib_runner's drive system into the core of the lang --- repl/lib_runner.c | 155 +++----------------------------------- repl/lib_runner.h | 27 ------- repl/repl_main.c | 21 ++---- source/toy.h | 1 + source/toy_drive_system.c | 99 ++++++++++++++++++++++++ source/toy_drive_system.h | 12 +++ test/test_libraries.c | 13 +--- 7 files changed, 133 insertions(+), 195 deletions(-) create mode 100644 source/toy_drive_system.c create mode 100644 source/toy_drive_system.h diff --git a/repl/lib_runner.c b/repl/lib_runner.c index 4b8ef80..27f05e7 100644 --- a/repl/lib_runner.c +++ b/repl/lib_runner.c @@ -1,13 +1,12 @@ #include "lib_runner.h" #include "toy_memory.h" +#include "toy_drive_system.h" #include "toy_interpreter.h" #include "repl_tools.h" -#include #include -#include typedef struct Toy_Runner { Toy_Interpreter interpreter; @@ -38,7 +37,7 @@ static int nativeLoadScript(Toy_Interpreter* interpreter, Toy_LiteralArray* argu return -1; } - Toy_Literal filePathLiteral = Toy_getFilePathLiteral(interpreter, &drivePathLiteral); + Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral); if (TOY_IS_NULL(filePathLiteral)) { Toy_freeLiteral(filePathLiteral); @@ -113,70 +112,19 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr return -1; } - Toy_RefString* drivePath = Toy_copyRefString(TOY_AS_STRING(drivePathLiteral)); + Toy_Literal filePathLiteral = Toy_getDrivePathLiteral(interpreter, &drivePathLiteral); - //get the drive and path as a string (can't trust that pesky strtok - custom split) TODO: move this to refstring library - size_t driveLength = 0; - while (Toy_toCString(drivePath)[driveLength] != ':') { - if (driveLength >= Toy_lengthRefString(drivePath)) { - interpreter->errorOutput("Incorrect drive path format given to loadScriptBytecode\n"); - Toy_deleteRefString(drivePath); - Toy_freeLiteral(drivePathLiteral); - return -1; - } - - driveLength++; - } - - Toy_RefString* drive = Toy_createRefStringLength(Toy_toCString(drivePath), driveLength); - Toy_RefString* path = Toy_createRefStringLength( &Toy_toCString(drivePath)[driveLength + 1], Toy_lengthRefString(drivePath) - driveLength ); - - //get the real drive file path - Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(drive); //NOTE: driveLiteral takes ownership of the refString - Toy_Literal realDriveLiteral = Toy_getLiteralDictionary(Toy_getDriveDictionary(), driveLiteral); - - if (!TOY_IS_STRING(realDriveLiteral)) { - interpreter->errorOutput("Incorrect literal type found for drive: "); - Toy_printLiteralCustom(realDriveLiteral, interpreter->errorOutput); - interpreter->errorOutput("\n"); - Toy_freeLiteral(realDriveLiteral); - Toy_freeLiteral(driveLiteral); - Toy_deleteRefString(path); - Toy_deleteRefString(drivePath); + if (TOY_IS_NULL(filePathLiteral)) { + Toy_freeLiteral(filePathLiteral); Toy_freeLiteral(drivePathLiteral); return -1; } - //get the final real file path (concat) TODO: move this concat to refstring library - Toy_RefString* realDrive = Toy_copyRefString(TOY_AS_STRING(realDriveLiteral)); - size_t realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path); - - char* filePath = TOY_ALLOCATE(char, realLength + 1); //+1 for null - snprintf(filePath, realLength, "%s%s", Toy_toCString(realDrive), Toy_toCString(path)); - - //clean up the drivepath stuff - Toy_deleteRefString(realDrive); - Toy_freeLiteral(realDriveLiteral); - Toy_freeLiteral(driveLiteral); - Toy_deleteRefString(path); - Toy_deleteRefString(drivePath); Toy_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"); - TOY_FREE_ARRAY(char, filePath, realLength); - return -1; - } - - //check for break-out attempts - for (size_t i = 0; i < realLength - 1; i++) { - if (filePath[i] == '.' && filePath[i + 1] == '.') { - interpreter->errorOutput("Parent directory access not allowed\n"); - TOY_FREE_ARRAY(char, filePath, realLength); - return -1; - } - } + //use raw types - easier + const char* filePath = Toy_toCString(TOY_AS_STRING(filePathLiteral)); + size_t filePathLength = Toy_lengthRefString(TOY_AS_STRING(filePathLiteral)); //load the bytecode size_t fileSize = 0; @@ -203,7 +151,8 @@ static int nativeLoadScriptBytecode(Toy_Interpreter* interpreter, Toy_LiteralArr Toy_Literal runnerLiteral = TOY_TO_OPAQUE_LITERAL(runner, TOY_OPAQUE_TAG_RUNNER); Toy_pushLiteralArray(&interpreter->stack, runnerLiteral); - TOY_FREE_ARRAY(char, filePath, realLength); + //free the drive path + Toy_freeLiteral(filePathLiteral); return 1; } @@ -602,87 +551,3 @@ int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Lit return 0; } -//file system API -static Toy_LiteralDictionary Toy_driveDictionary; - -void Toy_initDriveDictionary() { - Toy_initLiteralDictionary(&Toy_driveDictionary); -} - -void Toy_freeDriveDictionary() { - Toy_freeLiteralDictionary(&Toy_driveDictionary); -} - -Toy_LiteralDictionary* Toy_getDriveDictionary() { - return &Toy_driveDictionary; -} - -Toy_Literal Toy_getFilePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral) { - //check argument types - if (!TOY_IS_STRING(*drivePathLiteral)) { - interpreter->errorOutput("Incorrect argument type passed to Toy_getFilePathLiteral\n"); - return TOY_TO_NULL_LITERAL; - } - - Toy_RefString* drivePath = Toy_copyRefString(TOY_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 - size_t driveLength = 0; - while (Toy_toCString(drivePath)[driveLength] != ':') { - if (driveLength >= Toy_lengthRefString(drivePath)) { - interpreter->errorOutput("Incorrect drive path format given to Toy_getFilePathLiteral\n"); - - return TOY_TO_NULL_LITERAL; - } - - driveLength++; - } - - Toy_RefString* drive = Toy_createRefStringLength(Toy_toCString(drivePath), driveLength); - Toy_RefString* path = Toy_createRefStringLength( &Toy_toCString(drivePath)[driveLength + 1], Toy_lengthRefString(drivePath) - driveLength ); - - //get the real drive file path - Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(drive); //NOTE: driveLiteral takes ownership of the refString - Toy_Literal realDriveLiteral = Toy_getLiteralDictionary(Toy_getDriveDictionary(), driveLiteral); - - if (!TOY_IS_STRING(realDriveLiteral)) { - interpreter->errorOutput("Incorrect literal type found for drive: "); - Toy_printLiteralCustom(realDriveLiteral, interpreter->errorOutput); - interpreter->errorOutput("\n"); - Toy_freeLiteral(realDriveLiteral); - Toy_freeLiteral(driveLiteral); - Toy_deleteRefString(path); - Toy_deleteRefString(drivePath); - - return TOY_TO_NULL_LITERAL; - } - - //get the final real file path (concat) TODO: move this concat to refstring library - Toy_RefString* realDrive = Toy_copyRefString(TOY_AS_STRING(realDriveLiteral)); - size_t realLength = Toy_lengthRefString(realDrive) + Toy_lengthRefString(path); - - char* filePath = TOY_ALLOCATE(char, realLength + 1); //+1 for null - snprintf(filePath, realLength, "%s%s", Toy_toCString(realDrive), Toy_toCString(path)); - - //clean up the drivepath stuff - Toy_deleteRefString(realDrive); - Toy_freeLiteral(realDriveLiteral); - Toy_freeLiteral(driveLiteral); - Toy_deleteRefString(path); - Toy_deleteRefString(drivePath); - - //check for break-out attempts - for (size_t i = 0; i < realLength - 1; i++) { - if (filePath[i] == '.' && filePath[i + 1] == '.') { - interpreter->errorOutput("Parent directory access not allowed\n"); - TOY_FREE_ARRAY(char, filePath, realLength + 1); - return TOY_TO_NULL_LITERAL; - } - } - - Toy_Literal result = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(filePath, realLength)); - - TOY_FREE_ARRAY(char, filePath, realLength + 1); - - return result; -} \ No newline at end of file diff --git a/repl/lib_runner.h b/repl/lib_runner.h index 5c5b81c..549c2ac 100644 --- a/repl/lib_runner.h +++ b/repl/lib_runner.h @@ -1,35 +1,8 @@ #pragma once -#include "toy_common.h" #include "toy_interpreter.h" int Toy_hookRunner(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Literal alias); #define TOY_OPAQUE_TAG_RUNNER 100 -//platform/compiler-specific instructions - because MSVC + Box Engine are dumber than a bag of rocks -#if defined(__linux__) || defined(__MINGW32__) || defined(__GNUC__) - -#define LIB_RUNNER_API extern - -#elif defined(_MSC_VER) - -#ifndef LIB_RUNNER_EXPORT -#define LIB_RUNNER_API __declspec(dllimport) -#else -#define LIB_RUNNER_API __declspec(dllexport) -#endif - -#else - -#define LIB_RUNNER_API extern - -#endif - -//file system API - these need to be set by the host -LIB_RUNNER_API void Toy_initDriveDictionary(); -LIB_RUNNER_API void Toy_freeDriveDictionary(); -LIB_RUNNER_API Toy_LiteralDictionary* Toy_getDriveDictionary(); - -//file system API - for use with other libs -LIB_RUNNER_API Toy_Literal Toy_getFilePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral); diff --git a/repl/repl_main.c b/repl/repl_main.c index a3b64f6..24f2c90 100644 --- a/repl/repl_main.c +++ b/repl/repl_main.c @@ -103,16 +103,9 @@ void repl(const char* initialInput) { int main(int argc, const char* argv[]) { Toy_initCommandLine(argc, argv); - //lib setup (hacky - only really for this program) - Toy_initDriveDictionary(); - - Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("scripts")); - Toy_Literal pathLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("scripts")); - - Toy_setLiteralDictionary(Toy_getDriveDictionary(), driveLiteral, pathLiteral); - - Toy_freeLiteral(driveLiteral); - Toy_freeLiteral(pathLiteral); + //setup the drive system (for filesystem access) + Toy_initDriveSystem(); + Toy_setDrivePath("scripts", "scripts"); //command line specific actions if (Toy_commandLine.error) { @@ -148,7 +141,7 @@ int main(int argc, const char* argv[]) { Toy_runSourceFile(Toy_commandLine.sourcefile); //lib cleanup - Toy_freeDriveDictionary(); + Toy_freeDriveSystem(); return 0; } @@ -158,7 +151,7 @@ int main(int argc, const char* argv[]) { Toy_runSource(Toy_commandLine.source); //lib cleanup - Toy_freeDriveDictionary(); + Toy_freeDriveSystem(); return 0; } @@ -204,7 +197,7 @@ int main(int argc, const char* argv[]) { Toy_runBinaryFile(Toy_commandLine.binaryfile); //lib cleanup - Toy_freeDriveDictionary(); + Toy_freeDriveSystem(); return 0; } @@ -225,7 +218,7 @@ int main(int argc, const char* argv[]) { repl(initialSource); //lib cleanup - Toy_freeDriveDictionary(); + Toy_freeDriveSystem(); return 0; } diff --git a/source/toy.h b/source/toy.h index 4f146d6..97f0f66 100644 --- a/source/toy.h +++ b/source/toy.h @@ -16,6 +16,7 @@ The most important one is `TOY_API`, which highlights functions intended for the #include "toy_common.h" #include "toy_console_colors.h" #include "toy_memory.h" +#include "toy_drive_system.h" /* core pipeline - from source to execution diff --git a/source/toy_drive_system.c b/source/toy_drive_system.c new file mode 100644 index 0000000..2137e42 --- /dev/null +++ b/source/toy_drive_system.c @@ -0,0 +1,99 @@ +#include "toy_drive_system.h" + +#include "toy_memory.h" +#include "toy_literal_dictionary.h" + +#include +#include +#include + +//file system API +static Toy_LiteralDictionary driveDictionary; + +void Toy_initDriveSystem() { + Toy_initLiteralDictionary(&driveDictionary); +} + +void Toy_freeDriveSystem() { + Toy_freeLiteralDictionary(&driveDictionary); +} + +TOY_API void Toy_setDrivePath(char* drive, char* path) { + Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(drive)); + Toy_Literal pathLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString(path)); + + Toy_setLiteralDictionary(&driveDictionary, driveLiteral, pathLiteral); + + Toy_freeLiteral(driveLiteral); + Toy_freeLiteral(pathLiteral); +} + +Toy_Literal Toy_getDrivePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral) { + //check argument types + if (!TOY_IS_STRING(*drivePathLiteral)) { + interpreter->errorOutput("Incorrect argument type passed to Toy_getDrivePathLiteral\n"); + return TOY_TO_NULL_LITERAL; + } + + Toy_RefString* drivePath = Toy_copyRefString(TOY_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 + size_t driveLength = 0; + while (Toy_toCString(drivePath)[driveLength] != ':') { + if (driveLength >= Toy_lengthRefString(drivePath)) { + interpreter->errorOutput("Incorrect drive path format given to Toy_getDrivePathLiteral\n"); + + return TOY_TO_NULL_LITERAL; + } + + driveLength++; + } + + Toy_RefString* drive = Toy_createRefStringLength(Toy_toCString(drivePath), driveLength); + Toy_RefString* filePath = Toy_createRefStringLength( &Toy_toCString(drivePath)[driveLength + 1], Toy_lengthRefString(drivePath) - driveLength ); + + //get the real drive file path + Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(drive); //NOTE: driveLiteral takes ownership of the refString + Toy_Literal pathLiteral = Toy_getLiteralDictionary(&driveDictionary, driveLiteral); + + if (!TOY_IS_STRING(pathLiteral)) { + interpreter->errorOutput("Incorrect literal type found for drive: "); + Toy_printLiteralCustom(pathLiteral, interpreter->errorOutput); + interpreter->errorOutput("\n"); + Toy_freeLiteral(driveLiteral); + Toy_freeLiteral(pathLiteral); + Toy_deleteRefString(filePath); + Toy_deleteRefString(drivePath); + + return TOY_TO_NULL_LITERAL; + } + + //get the final real file path (concat) TODO: move this concat to refstring library + Toy_RefString* path = Toy_copyRefString(TOY_AS_STRING(pathLiteral)); + size_t fileLength = Toy_lengthRefString(path) + Toy_lengthRefString(filePath); + + char* file = TOY_ALLOCATE(char, fileLength + 1); //+1 for null + snprintf(file, fileLength, "%s%s", Toy_toCString(drive), Toy_toCString(filePath)); + + //clean up the drive/path stuff + Toy_deleteRefString(drivePath); + Toy_deleteRefString(filePath); + Toy_deleteRefString(path); + Toy_freeLiteral(driveLiteral); + Toy_freeLiteral(pathLiteral); + + //check for break-out attempts + for (size_t i = 0; i < fileLength - 1; i++) { + if (file[i] == '.' && file[i + 1] == '.') { + interpreter->errorOutput("Parent directory access not allowed\n"); + TOY_FREE_ARRAY(char, file, fileLength + 1); + return TOY_TO_NULL_LITERAL; + } + } + + Toy_Literal result = TOY_TO_STRING_LITERAL(Toy_createRefStringLength(file, fileLength)); + + TOY_FREE_ARRAY(char, file, fileLength + 1); + + return result; +} \ No newline at end of file diff --git a/source/toy_drive_system.h b/source/toy_drive_system.h new file mode 100644 index 0000000..2f20f22 --- /dev/null +++ b/source/toy_drive_system.h @@ -0,0 +1,12 @@ +#include "toy_common.h" + +#include "toy_literal.h" +#include "toy_interpreter.h" + +//file system API - these need to be set by the host +TOY_API void Toy_initDriveSystem(); +TOY_API void Toy_freeDriveSystem(); + +//file system API - for use with libs +TOY_API void Toy_setDrivePath(char* drive, char* path); +TOY_API Toy_Literal Toy_getDrivePathLiteral(Toy_Interpreter* interpreter, Toy_Literal* drivePathLiteral); diff --git a/test/test_libraries.c b/test/test_libraries.c index dadd25b..886ea6e 100644 --- a/test/test_libraries.c +++ b/test/test_libraries.c @@ -6,6 +6,7 @@ #include "toy_console_colors.h" #include "toy_memory.h" +#include "toy_drive_system.h" #include #include @@ -63,15 +64,9 @@ typedef struct Payload { int main() { //setup the runner filesystem (hacky) - Toy_initDriveDictionary(); + Toy_initDriveSystem(); - Toy_Literal driveLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("scripts")); - Toy_Literal pathLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("scripts")); - - Toy_setLiteralDictionary(Toy_getDriveDictionary(), driveLiteral, pathLiteral); - - Toy_freeLiteral(driveLiteral); - Toy_freeLiteral(pathLiteral); + Toy_setDrivePath("scripts", "scripts"); { //run each file in test/scripts @@ -113,7 +108,7 @@ int main() { } //lib cleanup - Toy_freeDriveDictionary(); + Toy_freeDriveSystem(); if (!failedAsserts) { printf(TOY_CC_NOTICE "All good\n" TOY_CC_RESET);