blob: 8203ad5049c34c37ac5d8d4f59ab6b22be10cc20 [file] [log] [blame]
John Kessenicha0af4732012-12-12 21:15:54 +00001//
2//Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
John Kessenichbd0747d2013-02-17 06:01:50 +00003//Copyright (C) 2013 LunarG, Inc.
4//
John Kessenicha0af4732012-12-12 21:15:54 +00005//All rights reserved.
6//
7//Redistribution and use in source and binary forms, with or without
8//modification, are permitted provided that the following conditions
9//are met:
10//
11// Redistributions of source code must retain the above copyright
12// notice, this list of conditions and the following disclaimer.
13//
14// Redistributions in binary form must reproduce the above
15// copyright notice, this list of conditions and the following
16// disclaimer in the documentation and/or other materials provided
17// with the distribution.
18//
19// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20// contributors may be used to endorse or promote products derived
21// from this software without specific prior written permission.
22//
23//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34//POSSIBILITY OF SUCH DAMAGE.
35//
John Kessenich2b07c7e2013-07-31 18:44:13 +000036#include "Worklist.h"
John Kessenicha0af4732012-12-12 21:15:54 +000037#include "./../glslang/Include/ShHandle.h"
38#include "./../glslang/Public/ShaderLang.h"
39#include <string.h>
John Kessenichcfd643e2013-03-08 23:14:42 +000040#include <stdlib.h>
John Kessenicha0af4732012-12-12 21:15:54 +000041#include <math.h>
42
John Kessenich2b07c7e2013-07-31 18:44:13 +000043#include "osinclude.h"
John Kessenicha0af4732012-12-12 21:15:54 +000044
45extern "C" {
46 SH_IMPORT_EXPORT void ShOutputHtml();
47}
48
John Kessenich94a81fb2013-08-31 02:41:30 +000049// Command-line options
50enum TOptions {
51 EOptionNone = 0x000,
52 EOptionIntermediate = 0x001,
53 EOptionSuppressInfolog = 0x002,
54 EOptionMemoryLeakMode = 0x004,
55 EOptionRelaxedErrors = 0x008,
56 EOptionGiveWarnings = 0x010,
57 EOptionsLinkProgram = 0x020,
John Kessenich38f3b892013-09-06 19:52:57 +000058 EOptionMultiThreaded = 0x040,
John Kessenich94a81fb2013-08-31 02:41:30 +000059};
60
John Kessenicha0af4732012-12-12 21:15:54 +000061//
62// Return codes from main.
63//
64enum TFailCode {
65 ESuccess = 0,
66 EFailUsage,
67 EFailCompile,
68 EFailLink,
69 EFailCompilerCreate,
John Kessenich2b07c7e2013-07-31 18:44:13 +000070 EFailThreadCreate,
John Kessenicha0af4732012-12-12 21:15:54 +000071 EFailLinkerCreate
72};
73
74//
75// Just placeholders for testing purposes. The stand-alone environment
76// can't actually do a full link without something specifying real
77// attribute bindings.
78//
79ShBinding FixedAttributeBindings[] = {
80 { "gl_Vertex", 15 },
81 { "gl_Color", 10 },
82 { "gl_Normal", 7 },
83};
84
85ShBindingTable FixedAttributeTable = { 3, FixedAttributeBindings };
86
John Kessenichb603f912013-08-29 00:39:25 +000087EShLanguage FindLanguage(const std::string& name);
John Kessenich52ac67e2013-05-05 23:46:22 +000088bool CompileFile(const char *fileName, ShHandle, int options, const TBuiltInResource*);
John Kessenicha0af4732012-12-12 21:15:54 +000089void usage();
90void FreeFileData(char **data);
John Kessenich54d8cda2013-02-11 22:36:01 +000091char** ReadFileData(const char *fileName);
92void InfoLogMsg(const char* msg, const char* name, const int num);
John Kessenich41cf6b52013-06-25 18:10:05 +000093
94// Use to test breaking a single shader file into multiple strings.
95int NumShaderStrings = 1;
John Kessenicha0af4732012-12-12 21:15:54 +000096
97//
98// Set up the per compile resources
99//
100void GenerateResources(TBuiltInResource& resources)
John Kessenichb51f62c2013-04-11 16:31:09 +0000101{
John Kessenicha0af4732012-12-12 21:15:54 +0000102 resources.maxLights = 32;
103 resources.maxClipPlanes = 6;
104 resources.maxTextureUnits = 32;
105 resources.maxTextureCoords = 32;
106 resources.maxVertexAttribs = 64;
107 resources.maxVertexUniformComponents = 4096;
108 resources.maxVaryingFloats = 64;
109 resources.maxVertexTextureImageUnits = 32;
110 resources.maxCombinedTextureImageUnits = 32;
111 resources.maxTextureImageUnits = 32;
112 resources.maxFragmentUniformComponents = 4096;
113 resources.maxDrawBuffers = 32;
John Kessenichbd0747d2013-02-17 06:01:50 +0000114 resources.maxVertexUniformVectors = 128;
115 resources.maxVaryingVectors = 8;
116 resources.maxFragmentUniformVectors = 16;
117 resources.maxVertexOutputVectors = 16;
John Kessenich1f2a36b2013-02-20 04:42:42 +0000118 resources.maxFragmentInputVectors = 15;
John Kessenichbd0747d2013-02-17 06:01:50 +0000119 resources.minProgramTexelOffset = -8;
120 resources.maxProgramTexelOffset = 7;
John Kessenicha0af4732012-12-12 21:15:54 +0000121}
122
John Kessenich38f3b892013-09-06 19:52:57 +0000123// thread-safe list of shaders to asynchronously grab and compile
John Kessenich2b07c7e2013-07-31 18:44:13 +0000124glslang::TWorklist Worklist;
John Kessenich38f3b892013-09-06 19:52:57 +0000125
126// array of unique places to leave the shader names and infologs for the asynchronous compiles
127glslang::TWorkItem **Work = 0;
128int NumWorkItems = 0;
129
John Kessenich94a81fb2013-08-31 02:41:30 +0000130int Options = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000131bool Delay = false;
John Kessenich38f3b892013-09-06 19:52:57 +0000132const char* ExecutableName;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000133
134bool ProcessArguments(int argc, char* argv[])
135{
John Kessenich38f3b892013-09-06 19:52:57 +0000136 ExecutableName = argv[0];
137 NumWorkItems = argc; // will include some empties where the '-' options were, but it doesn't matter, they'll be 0
138 Work = new glslang::TWorkItem*[NumWorkItems];
139 Work[0] = 0;
140
John Kessenich2b07c7e2013-07-31 18:44:13 +0000141 argc--;
142 argv++;
143 for (; argc >= 1; argc--, argv++) {
144 if (argv[0][0] == '-') {
John Kessenich38f3b892013-09-06 19:52:57 +0000145 Work[argc] = 0;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000146 switch (argv[0][1]) {
147 case 'd':
148 Delay = true;
149 break;
150 case 'i':
John Kessenich94a81fb2013-08-31 02:41:30 +0000151 Options |= EOptionIntermediate;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000152 break;
153 case 'l':
John Kessenich94a81fb2013-08-31 02:41:30 +0000154 Options |= EOptionsLinkProgram;
155 break;
156 case 'm':
157 Options |= EOptionMemoryLeakMode;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000158 break;
159 case 'r':
John Kessenich94a81fb2013-08-31 02:41:30 +0000160 Options |= EOptionRelaxedErrors;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000161 break;
162 case 's':
John Kessenich94a81fb2013-08-31 02:41:30 +0000163 Options |= EOptionSuppressInfolog;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000164 break;
John Kessenich38f3b892013-09-06 19:52:57 +0000165 case 't':
166 #ifdef _WIN32
167 Options |= EOptionMultiThreaded;
168 #endif
169 break;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000170 default:
John Kessenich2b07c7e2013-07-31 18:44:13 +0000171 return false;
172 }
John Kessenich38f3b892013-09-06 19:52:57 +0000173 } else {
174 Work[argc] = new glslang::TWorkItem(std::string(argv[0]));
175 Worklist.add(Work[argc]);
176 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000177 }
178
John Kessenich54f6e562013-08-03 00:04:10 +0000179 if (Worklist.empty())
180 return false;
181
John Kessenich2b07c7e2013-07-31 18:44:13 +0000182 return true;
183}
184
John Kessenich69f4b512013-09-04 21:19:27 +0000185// Thread entry point, for non-linking asynchronous mode.
John Kessenichee6a9c82013-07-31 23:19:17 +0000186unsigned int
187#ifdef _WIN32
188 __stdcall
189#endif
John Kessenich94a81fb2013-08-31 02:41:30 +0000190CompileShaders(void*)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000191{
John Kessenich38f3b892013-09-06 19:52:57 +0000192 glslang::TWorkItem* workItem;
193 while (Worklist.remove(workItem)) {
194 ShHandle compiler = ShConstructCompiler(FindLanguage(workItem->name), Options);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000195 if (compiler == 0)
196 return false;
197
198 TBuiltInResource resources;
199 GenerateResources(resources);
John Kessenich38f3b892013-09-06 19:52:57 +0000200 CompileFile(workItem->name.c_str(), compiler, Options, &resources);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000201
John Kessenich94a81fb2013-08-31 02:41:30 +0000202 if (! (Options & EOptionSuppressInfolog))
John Kessenich38f3b892013-09-06 19:52:57 +0000203 workItem->results = ShGetInfoLog(compiler);
John Kessenich2b07c7e2013-07-31 18:44:13 +0000204
205 ShDestruct(compiler);
206 }
207
208 return 0;
209}
210
John Kessenich69f4b512013-09-04 21:19:27 +0000211//
212// For linking mode: Will independently parse each item in the worklist, but then put them
213// in the same program and link them together.
214//
215// Uses the new C++ interface instead of the old handle-based interface.
216//
217void CompileAndLinkShaders()
218{
219 // keep track of what to free
220 std::list<glslang::TShader*> shaders;
221
222 EShMessages messages = EShMsgDefault;
223 if (Options & EOptionRelaxedErrors)
224 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
225 if (Options & EOptionIntermediate)
226 messages = (EShMessages)(messages | EShMsgAST);
227
228 TBuiltInResource resources;
229 GenerateResources(resources);
230
231 //
232 // Per-shader processing...
233 //
234
235 glslang::TProgram program;
John Kessenich38f3b892013-09-06 19:52:57 +0000236 glslang::TWorkItem* workItem;
237 while (Worklist.remove(workItem)) {
238 EShLanguage stage = FindLanguage(workItem->name);
John Kessenich69f4b512013-09-04 21:19:27 +0000239 glslang::TShader* shader = new glslang::TShader(stage);
240 shaders.push_back(shader);
241
John Kessenich38f3b892013-09-06 19:52:57 +0000242 char** shaderStrings = ReadFileData(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000243 if (! shaderStrings) {
244 usage();
245 return;
246 }
247
248 shader->setStrings(shaderStrings, 1);
249
250 shader->parse(&resources, 100, false, messages);
251
252 program.addShader(shader);
253
254 if (! (Options & EOptionSuppressInfolog)) {
John Kessenich38f3b892013-09-06 19:52:57 +0000255 puts(workItem->name.c_str());
John Kessenich69f4b512013-09-04 21:19:27 +0000256 puts(shader->getInfoLog());
257 puts(shader->getInfoDebugLog());
258 }
259
260 FreeFileData(shaderStrings);
261 }
262
263 //
264 // Program-level processing...
265 //
266
267 program.link(messages);
268 if (! (Options & EOptionSuppressInfolog)) {
269 puts(program.getInfoLog());
270 puts(program.getInfoDebugLog());
271 }
272
273 // free everything up
274 while (shaders.size() > 0) {
275 delete shaders.back();
276 shaders.pop_back();
277 }
278
279 // TODO: memory: for each compile, need a GetThreadPoolAllocator().pop();
280}
281
John Kessenicha0af4732012-12-12 21:15:54 +0000282int C_DECL main(int argc, char* argv[])
283{
John Kessenicha0af4732012-12-12 21:15:54 +0000284 bool compileFailed = false;
285 bool linkFailed = false;
John Kessenicha0af4732012-12-12 21:15:54 +0000286
John Kessenich2b07c7e2013-07-31 18:44:13 +0000287 // Init for front-end proper
John Kessenicha0af4732012-12-12 21:15:54 +0000288 ShInitialize();
289
John Kessenich38f3b892013-09-06 19:52:57 +0000290 // Init for standalone
John Kessenich2b07c7e2013-07-31 18:44:13 +0000291 glslang::InitGlobalLock();
John Kessenicha0af4732012-12-12 21:15:54 +0000292
John Kessenich54f6e562013-08-03 00:04:10 +0000293 if (! ProcessArguments(argc, argv)) {
294 usage();
John Kessenich2b07c7e2013-07-31 18:44:13 +0000295 return EFailUsage;
John Kessenich54f6e562013-08-03 00:04:10 +0000296 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000297
John Kessenich69f4b512013-09-04 21:19:27 +0000298 //
299 // Two modes:
John Kessenich38f3b892013-09-06 19:52:57 +0000300 // 1) linking all arguments together, single-threaded, new C++ interface
301 // 2) independent arguments, can be tackled by multiple asynchronous threads, for testing thread safety, using the old handle interface
John Kessenich69f4b512013-09-04 21:19:27 +0000302 //
John Kessenich38f3b892013-09-06 19:52:57 +0000303 if (Options & EOptionsLinkProgram)
304 CompileAndLinkShaders();
305 else {
306 bool printShaderNames = Worklist.size() > 1;
John Kessenich69f4b512013-09-04 21:19:27 +0000307
John Kessenich38f3b892013-09-06 19:52:57 +0000308 if (Options & EOptionMultiThreaded) {
309 const int NumThreads = 16;
310 void* threads[NumThreads];
311 for (int t = 0; t < NumThreads; ++t) {
312 threads[t] = glslang::OS_CreateThread(&CompileShaders);
313 if (! threads[t]) {
314 printf("Failed to create thread\n");
315 return EFailThreadCreate;
316 }
John Kessenicha0af4732012-12-12 21:15:54 +0000317 }
John Kessenich38f3b892013-09-06 19:52:57 +0000318 glslang::OS_WaitForAllThreads(threads, NumThreads);
John Kessenich69f4b512013-09-04 21:19:27 +0000319 } else {
320 if (! CompileShaders(0))
321 compileFailed = true;
322 }
John Kessenich38f3b892013-09-06 19:52:57 +0000323
324 // Print out all the resulting infologs
325 for (int w = 0; w < NumWorkItems; ++w) {
326 if (Work[w]) {
327 if (printShaderNames)
328 puts(Work[w]->name.c_str());
329 puts(Work[w]->results.c_str());
330 delete Work[w];
331 }
332 }
John Kessenicha0af4732012-12-12 21:15:54 +0000333 }
John Kessenich2b07c7e2013-07-31 18:44:13 +0000334
335 if (Delay)
336 glslang::OS_Sleep(1000000);
John Kessenicha0af4732012-12-12 21:15:54 +0000337
338 if (compileFailed)
339 return EFailCompile;
340 if (linkFailed)
341 return EFailLink;
342
343 return 0;
344}
345
346//
347// Deduce the language from the filename. Files must end in one of the
348// following extensions:
349//
John Kessenich2b07c7e2013-07-31 18:44:13 +0000350// .vert = vertex
351// .tesc = tessellation control
352// .tese = tessellation evaluation
353// .geom = geometry
354// .frag = fragment
John Kessenich94a81fb2013-08-31 02:41:30 +0000355// .comp = compute
John Kessenicha0af4732012-12-12 21:15:54 +0000356//
John Kessenichb603f912013-08-29 00:39:25 +0000357EShLanguage FindLanguage(const std::string& name)
John Kessenicha0af4732012-12-12 21:15:54 +0000358{
John Kessenich2b07c7e2013-07-31 18:44:13 +0000359 size_t ext = name.rfind('.');
360 if (ext == std::string::npos) {
361 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000362 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000363 }
364
John Kessenich2b07c7e2013-07-31 18:44:13 +0000365 std::string suffix = name.substr(ext + 1, std::string::npos);
366 if (suffix == "vert")
367 return EShLangVertex;
368 else if (suffix == "tesc")
369 return EShLangTessControl;
370 else if (suffix == "tese")
371 return EShLangTessEvaluation;
372 else if (suffix == "geom")
373 return EShLangGeometry;
374 else if (suffix == "frag")
375 return EShLangFragment;
John Kessenichc0275792013-08-09 17:14:49 +0000376 else if (suffix == "comp")
377 return EShLangCompute;
John Kessenich2b07c7e2013-07-31 18:44:13 +0000378
379 usage();
John Kesseniche95ecc52012-12-12 21:34:14 +0000380 return EShLangVertex;
John Kessenicha0af4732012-12-12 21:15:54 +0000381}
382
John Kessenicha0af4732012-12-12 21:15:54 +0000383//
John Kessenich69f4b512013-09-04 21:19:27 +0000384// Read a file's data into a string, and compile it using the old interface ShCompile,
385// for non-linkable results.
John Kessenicha0af4732012-12-12 21:15:54 +0000386//
John Kessenich69f4b512013-09-04 21:19:27 +0000387bool CompileFile(const char *fileName, ShHandle compiler, int Options, const TBuiltInResource* resources)
John Kessenicha0af4732012-12-12 21:15:54 +0000388{
389 int ret;
John Kessenich41cf6b52013-06-25 18:10:05 +0000390 char** shaderStrings = ReadFileData(fileName);
John Kessenichdb4cd542013-06-26 22:42:55 +0000391 if (! shaderStrings) {
392 usage();
393 return false;
394 }
395
John Kessenich41cf6b52013-06-25 18:10:05 +0000396 int* lengths = new int[NumShaderStrings];
397
398 // move to length-based strings, rather than null-terminated strings
399 for (int s = 0; s < NumShaderStrings; ++s)
400 lengths[s] = strlen(shaderStrings[s]);
John Kessenich09da79e2013-04-17 19:34:23 +0000401
John Kessenich41cf6b52013-06-25 18:10:05 +0000402 if (! shaderStrings)
John Kessenicha0af4732012-12-12 21:15:54 +0000403 return false;
404
John Kessenich52ac67e2013-05-05 23:46:22 +0000405 EShMessages messages = EShMsgDefault;
John Kessenich94a81fb2013-08-31 02:41:30 +0000406 if (Options & EOptionRelaxedErrors)
John Kessenich52ac67e2013-05-05 23:46:22 +0000407 messages = (EShMessages)(messages | EShMsgRelaxedErrors);
John Kessenich94a81fb2013-08-31 02:41:30 +0000408 if (Options & EOptionIntermediate)
409 messages = (EShMessages)(messages | EShMsgAST);
John Kessenich69f4b512013-09-04 21:19:27 +0000410
John Kessenich94a81fb2013-08-31 02:41:30 +0000411 for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
412 for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
413 //ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, resources, Options, 100, false, messages);
414 ret = ShCompile(compiler, shaderStrings, NumShaderStrings, 0, EShOptNone, resources, Options, 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000415 //const char* multi[4] = { "# ve", "rsion", " 300 e", "s" };
416 //const char* multi[7] = { "/", "/", "\\", "\n", "\n", "#", "version 300 es" };
John Kessenich94a81fb2013-08-31 02:41:30 +0000417 //ret = ShCompile(compiler, multi, 4, 0, EShOptNone, resources, Options, 100, false, messages);
John Kessenich41cf6b52013-06-25 18:10:05 +0000418 }
John Kessenicha0af4732012-12-12 21:15:54 +0000419
John Kessenich94a81fb2013-08-31 02:41:30 +0000420 if (Options & EOptionMemoryLeakMode)
John Kessenich2b07c7e2013-07-31 18:44:13 +0000421 glslang::OS_DumpMemoryCounters();
John Kessenicha0af4732012-12-12 21:15:54 +0000422 }
John Kessenicha0af4732012-12-12 21:15:54 +0000423
John Kessenich41cf6b52013-06-25 18:10:05 +0000424 delete [] lengths;
425 FreeFileData(shaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000426
427 return ret ? true : false;
428}
429
John Kessenicha0af4732012-12-12 21:15:54 +0000430//
431// print usage to stdout
432//
433void usage()
434{
John Kessenich38f3b892013-09-06 19:52:57 +0000435 printf("Usage: glslangValidator [ options ] filename\n"
John Kessenichc0275792013-08-09 17:14:49 +0000436 "Where: filename is a name ending in\n"
437 " .vert for a vertex shader\n"
438 " .tesc for a tessellation control shader\n"
439 " .tese for a tessellation evaluation shader\n"
440 " .geom for a geometry shader\n"
441 " .frag for a fragment shader\n"
442 " .comp for a compute shader\n\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000443 "Compilation warnings and errors will be printed to stdout.\n"
444 "To get other information, use one of the following options:\n"
445 "-i: intermediate tree (glslang AST) is printed out\n"
446 "-d: delay exit\n"
John Kessenich94a81fb2013-08-31 02:41:30 +0000447 "-l: link validation of all input files\n"
448 "-m: memory leak mode\n"
John Kessenich38f3b892013-09-06 19:52:57 +0000449 "-r: relaxed semantic error-checking mode\n"
John Kessenich4586dbd2013-08-05 15:52:03 +0000450 "-s: silent mode\n"
John Kessenich38f3b892013-09-06 19:52:57 +0000451 "-t: multi-threaded mode\n");
John Kessenicha0af4732012-12-12 21:15:54 +0000452}
453
John Kessenichcfd643e2013-03-08 23:14:42 +0000454#ifndef _WIN32
455
456#include <errno.h>
457
458int fopen_s(
459 FILE** pFile,
460 const char *filename,
461 const char *mode
462)
463{
464 if (!pFile || !filename || !mode) {
465 return EINVAL;
466 }
467
468 FILE* f = fopen(filename, mode);
469 if (! f) {
470 if (errno != 0) {
471 return errno;
472 } else {
473 return ENOENT;
474 }
475 }
476 *pFile = f;
477
478 return 0;
479}
480
481#endif
482
John Kessenicha0af4732012-12-12 21:15:54 +0000483//
484// Malloc a string of sufficient size and read a string into it.
485//
John Kessenich54d8cda2013-02-11 22:36:01 +0000486char** ReadFileData(const char *fileName)
John Kessenicha0af4732012-12-12 21:15:54 +0000487{
John Kessenich200b2732012-12-12 21:21:23 +0000488 FILE *in;
489 int errorCode = fopen_s(&in, fileName, "r");
John Kessenicha0af4732012-12-12 21:15:54 +0000490 char *fdata;
491 int count = 0;
John Kessenichcfd643e2013-03-08 23:14:42 +0000492 const int maxSourceStrings = 5;
493 char** return_data = (char**)malloc(maxSourceStrings+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000494
495 //return_data[MAX_SOURCE_STRINGS]=NULL;
John Kessenich200b2732012-12-12 21:21:23 +0000496 if (errorCode) {
John Kessenicha0af4732012-12-12 21:15:54 +0000497 printf("Error: unable to open input file: %s\n", fileName);
498 return 0;
499 }
500
501 while (fgetc(in) != EOF)
502 count++;
503
504 fseek(in, 0, SEEK_SET);
505
506
507 if (!(fdata = (char *)malloc(count+2))) {
508 printf("Error allocating memory\n");
509 return 0;
510 }
511 if (fread(fdata,1,count, in)!=count) {
512 printf("Error reading input file: %s\n", fileName);
513 return 0;
514 }
515 fdata[count] = '\0';
516 fclose(in);
517 if(count==0){
518 return_data[0]=(char*)malloc(count+2);
519 return_data[0][0]='\0';
John Kessenich41cf6b52013-06-25 18:10:05 +0000520 NumShaderStrings=0;
John Kessenicha0af4732012-12-12 21:15:54 +0000521 return return_data;
522 }
523
John Kessenich41cf6b52013-06-25 18:10:05 +0000524 int len = (int)(ceil)((float)count/(float)NumShaderStrings);
John Kessenicha0af4732012-12-12 21:15:54 +0000525 int ptr_len=0,i=0;
526 while(count>0){
527 return_data[i]=(char*)malloc(len+2);
528 memcpy(return_data[i],fdata+ptr_len,len);
529 return_data[i][len]='\0';
530 count-=(len);
531 ptr_len+=(len);
532 if(count<len){
533 if(count==0){
John Kessenich41cf6b52013-06-25 18:10:05 +0000534 NumShaderStrings=(i+1);
John Kessenicha0af4732012-12-12 21:15:54 +0000535 break;
536 }
537 len = count;
538 }
539 ++i;
540 }
541 return return_data;
542}
543
John Kessenicha0af4732012-12-12 21:15:54 +0000544void FreeFileData(char **data)
545{
John Kessenich41cf6b52013-06-25 18:10:05 +0000546 for(int i=0;i<NumShaderStrings;i++)
John Kessenicha0af4732012-12-12 21:15:54 +0000547 free(data[i]);
548}
549
John Kessenich54d8cda2013-02-11 22:36:01 +0000550void InfoLogMsg(const char* msg, const char* name, const int num)
John Kessenicha0af4732012-12-12 21:15:54 +0000551{
552 printf(num >= 0 ? "#### %s %s %d INFO LOG ####\n" :
553 "#### %s %s INFO LOG ####\n", msg, name, num);
554}