1 #include <bz/scripting/script_internal.h>
3 #include <bz/memory/allocator.h>
4 #include <bz/resources/resource.h>
5 //#include <bz/scripting/bindings_internal.h>
6 //#include <bz/scripting/environment_internal.h>
7 #include <bz/types/identifier_internal.h>
8 #include <sun/compiler/compiler.h>
11 #define kMaxIncludeDepth 8
13 struct BZScriptReadContext {
14 size_t currentHandleIdx;
15 BZResourceID handles[kMaxIncludeDepth];
16 bool handlePreprocessor;
17 bool pastFirstCharacter;
19 typedef struct BZScriptReadContext BZScriptReadContext;
21 static size_t readSource(char *out, size_t outSize, void *userParam) {
22 BZScriptReadContext *context = userParam;
24 BZResourceID currentHandle = context->handles[context->currentHandleIdx];
25 size_t readStartPosition = bzResourcesTell(currentHandle);
28 if (context->handlePreprocessor) {
29 // Extract the current line...
31 size_t preprocessorLength = 0;
32 while (bzResourcesReadBytes(currentHandle, out, 1) > 0) {
36 preprocessorLength += 1;
39 char *preprocessorInstruction = alloca(preprocessorLength + 1);
40 preprocessorInstruction[preprocessorLength] = '\0';
41 bzResourcesSeek(currentHandle, readStartPosition);
42 bzResourcesReadBytes(currentHandle, preprocessorInstruction, preprocessorLength);
44 if (strncmp(preprocessorInstruction, "#include ", 9) == 0) {
45 context->currentHandleIdx++;
46 bzAssert(context->currentHandleIdx < kMaxIncludeDepth);
47 preprocessorInstruction += 9;
48 context->handles[context->currentHandleIdx] = bzResourcesOpenResource("script", "assets/scripts/%s", preprocessorInstruction);
49 bzAssertMessage(context->handles[context->currentHandleIdx] != NULL, "Invalid include '%s'", preprocessorInstruction);
54 while (readSize == 0) {
55 currentHandle = context->handles[context->currentHandleIdx];
56 readStartPosition = bzResourcesTell(currentHandle);
57 readSize = bzResourcesReadBytes(currentHandle, out, outSize);
60 if (context->currentHandleIdx > 0) {
61 bzResourcesCloseResource(currentHandle);
62 --context->currentHandleIdx;
64 // 0th level is closed in main code
70 for (size_t i = 0; i < readSize; ++i) {
73 if (context->pastFirstCharacter == false) {
74 // need to handle preprocessor, set flag and return only the read characters
75 bzResourcesSeek(currentHandle, readStartPosition + i);
76 context->handlePreprocessor = true;
79 return i; // don't return the '#' character
81 goto process; // I know this is horrible, don't @ me.
87 context->pastFirstCharacter = false;
92 // These still count as 'first character' techically...
96 context->pastFirstCharacter = true;
104 static void *sourceMalloc(void *memory, size_t size) {
108 SVMModule *bzScriptingLoadScriptModule(BZMemoryArenaID arena, const char *identifierFmt, ...) {
109 bzMakeIdentifier(identifier, identifierFmt);
111 BZScriptReadContext context = {
112 .handles = { bzResourcesOpenResource("script", "assets/scripts/%s.sun", identifier), },
113 .currentHandleIdx = 0,
114 .handlePreprocessor = false,
115 .pastFirstCharacter = false,
117 bzAssertMessage(context.handles[0] != NULL, "Invalid script '%s'", identifier);
119 SLCCompileConfiguration config = {
120 .sourceReadCallback = readSource,
121 .sourceUserParam = &context,
122 .realloc = sourceMalloc, // fixme
123 .free = NULL, // fixme
126 SVMModule *module = slcCompileSource(&config);
127 bzResourcesCloseResource(context.handles[0]);
129 if (module == NULL) {
130 bzError("Could not load script %s", identifier);