1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #include "BsSLPrerequisites.h" |
4 | #include "Material/BsShaderManager.h" |
5 | #include "Material/BsShaderInclude.h" |
6 | |
7 | extern "C" { |
8 | #include "BsIncludeHandler.h" |
9 | #include "BsMMAlloc.h" |
10 | } |
11 | |
12 | using namespace bs; |
13 | |
14 | char* includePush(ParseState* state, const char* filename, int line, int column, int* size) |
15 | { |
16 | int filenameQuotesLen = (int)strlen(filename); |
17 | char* filenameNoQuote = (char*)mmalloc(state->memContext, filenameQuotesLen - 1); |
18 | memcpy(filenameNoQuote, filename + 1, filenameQuotesLen - 2); |
19 | filenameNoQuote[filenameQuotesLen - 2] = '\0'; |
20 | |
21 | HShaderInclude include = ShaderManager::instance().findInclude(filenameNoQuote); |
22 | |
23 | if (include != nullptr) |
24 | include.blockUntilLoaded(); |
25 | |
26 | int filenameLen = (int)strlen(filenameNoQuote); |
27 | if (include.isLoaded()) |
28 | { |
29 | String includeSource = include->getString(); |
30 | |
31 | *size = (int)includeSource.size() + 2; |
32 | char* output = (char*)mmalloc(state->memContext, *size); |
33 | |
34 | memcpy(output, includeSource.data(), *size - 2); |
35 | output[*size - 2] = 0; |
36 | output[*size - 1] = 0; |
37 | |
38 | int linkSize = sizeof(IncludeLink) + sizeof(IncludeData) + filenameLen + 1; |
39 | char* linkData = (char*)mmalloc(state->memContext, linkSize); |
40 | |
41 | IncludeLink* newLink = (IncludeLink*)linkData; |
42 | linkData += sizeof(IncludeLink); |
43 | |
44 | IncludeData* includeData = (IncludeData*)linkData; |
45 | linkData += sizeof(IncludeData); |
46 | |
47 | memcpy(linkData, filenameNoQuote, filenameLen); |
48 | linkData[filenameLen] = '\0'; |
49 | |
50 | includeData->filename = linkData; |
51 | includeData->buffer = output; |
52 | |
53 | newLink->data = includeData; |
54 | newLink->next = state->includeStack; |
55 | |
56 | state->includeStack = newLink; |
57 | |
58 | mmfree(filenameNoQuote); |
59 | return output; |
60 | } |
61 | |
62 | const char* errorLabel = "Error opening include file: " ; |
63 | int labelLen = (int)strlen(errorLabel); |
64 | |
65 | int messageLen = filenameLen + labelLen + 1; |
66 | char* message = (char*)mmalloc(state->memContext, messageLen); |
67 | |
68 | memcpy(message, errorLabel, labelLen); |
69 | memcpy(message + labelLen, filenameNoQuote, filenameLen); |
70 | message[messageLen - 1] = '\0'; |
71 | |
72 | state->hasError = 1; |
73 | state->errorLine = line; |
74 | state->errorColumn = column; |
75 | state->errorMessage = message; |
76 | state->errorFile = getCurrentFilename(state); |
77 | |
78 | mmfree(filenameNoQuote); |
79 | return nullptr; |
80 | } |
81 | |
82 | void includePop(ParseState* state) |
83 | { |
84 | IncludeLink* current = state->includeStack; |
85 | |
86 | if (!current) |
87 | return; |
88 | |
89 | state->includeStack = current->next; |
90 | current->next = state->includes; |
91 | state->includes = current; |
92 | |
93 | mmfree(current->data->buffer); |
94 | current->data->buffer = nullptr; |
95 | } |