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
);