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
7extern "C" {
8#include "BsIncludeHandler.h"
9#include "BsMMAlloc.h"
10}
11
12using namespace bs;
13
14char* 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
82void 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}