Standalone: Rationalize ShaderCompUnit and file data.

ShaderCompUnit was poorly done, a mix of a list of things and hard
coding to a single thing. This makes it all a true list.

File data was greatly simplified to be a single string, no longer
supporting breaking a single file into multiple strings.
diff --git a/StandAlone/StandAlone.cpp b/StandAlone/StandAlone.cpp
index 74662d8..6469943 100644
--- a/StandAlone/StandAlone.cpp
+++ b/StandAlone/StandAlone.cpp
@@ -115,18 +115,14 @@
 EShLanguage FindLanguage(const std::string& name, bool parseSuffix=true);
 void CompileFile(const char* fileName, ShHandle);
 void usage();
-void FreeFileData(char** data);
-char** ReadFileData(const char* fileName);
+char* ReadFileData(const char* fileName);
+void FreeFileData(char* data);
 void InfoLogMsg(const char* msg, const char* name, const int num);
 
 // Globally track if any compile or link failure.
 bool CompileFailed = false;
 bool LinkFailed = false;
 
-// Use to test breaking up a single shader file into multiple strings.
-// Set in ReadFileData().
-int NumShaderStrings;
-
 TBuiltInResource Resources;
 std::string ConfigFile;
 
@@ -135,29 +131,13 @@
 //
 void ProcessConfigFile()
 {
-    char** configStrings = 0;
-    char* config = 0;
-    if (ConfigFile.size() > 0) {
-        configStrings = ReadFileData(ConfigFile.c_str());
-        if (configStrings)
-            config = *configStrings;
-        else {
-            printf("Error opening configuration file; will instead use the default configuration\n");
-            usage();
-        }
-    }
-
-    if (config == 0) {
+    if (ConfigFile.size() == 0)
         Resources = glslang::DefaultTBuiltInResource;
-        return;
+    else {
+        char* configString = ReadFileData(ConfigFile.c_str());
+        glslang::DecodeResourceLimits(&Resources,  configString);
+        FreeFileData(configString);
     }
-
-    glslang::DecodeResourceLimits(&Resources,  config);
-
-    if (configStrings)
-        FreeFileData(configStrings);
-    else
-        delete[] config;
 }
 
 int Options = 0;
@@ -594,36 +574,41 @@
 // This prevents erroneous newlines from appearing.
 void StderrIfNonEmpty(const char* str)
 {
-    if (str && str[0]) {
-      fprintf(stderr, "%s\n", str);
-    }
+    if (str && str[0])
+        fprintf(stderr, "%s\n", str);
 }
 
 // Simple bundling of what makes a compilation unit for ease in passing around,
 // and separation of handling file IO versus API (programmatic) compilation.
 struct ShaderCompUnit {
     EShLanguage stage;
-    std::string fileName;
-    char** text;             // memory owned/managed externally
-    const char* fileNameList[1];
+    static const int maxCount = 1;
+    int count;                          // live number of strings/names
+    char* text[maxCount];               // memory owned/managed externally
+    std::string fileName[maxCount];     // hold's the memory, but...
+    const char* fileNameList[maxCount]; // downstream interface wants pointers
 
-    // Need to have a special constructors to adjust the fileNameList, since back end needs a list of ptrs
-    ShaderCompUnit(EShLanguage istage, std::string &ifileName, char** itext)
-    {
-        stage = istage;
-        fileName = ifileName;
-        text = itext;
-        fileNameList[0] = fileName.c_str();
-    }
+    ShaderCompUnit(EShLanguage stage) : stage(stage), count(0) { }
 
-    ShaderCompUnit(const ShaderCompUnit &rhs)
+    ShaderCompUnit(const ShaderCompUnit& rhs)
     {
         stage = rhs.stage;
-        fileName = rhs.fileName;
-        text = rhs.text;
-        fileNameList[0] = fileName.c_str();
+        count = rhs.count;
+        for (int i = 0; i < count; ++i) {
+            fileName[i] = rhs.fileName[i];
+            text[i] = rhs.text[i];
+            fileNameList[i] = rhs.fileName[i].c_str();
+        }
     }
 
+    void addString(std::string& ifileName, char* itext)
+    {
+        assert(count < maxCount);
+        fileName[count] = ifileName;
+        text[count] = itext;
+        fileNameList[count] = fileName[count].c_str();
+        ++count;
+    }
 };
 
 //
@@ -650,7 +635,7 @@
     for (auto it = compUnits.cbegin(); it != compUnits.cend(); ++it) {
         const auto &compUnit = *it;
         glslang::TShader* shader = new glslang::TShader(compUnit.stage);
-        shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, 1);
+        shader->setStringsWithLengthsAndNames(compUnit.text, NULL, compUnit.fileNameList, compUnit.count);
         if (entryPointName) // HLSL todo: this needs to be tracked per compUnits
             shader->setEntryPoint(entryPointName);
         if (sourceEntryPointName)
@@ -701,7 +686,7 @@
 
         if (! (Options & EOptionSuppressInfolog) &&
             ! (Options & EOptionMemoryLeakMode)) {
-            PutsIfNonEmpty(compUnit.fileName.c_str());
+            PutsIfNonEmpty(compUnit.fileName[0].c_str());
             PutsIfNonEmpty(shader->getInfoLog());
             PutsIfNonEmpty(shader->getInfoDebugLog());
         }
@@ -802,17 +787,11 @@
     // they are all getting linked together.)
     glslang::TWorkItem* workItem;
     while (Worklist.remove(workItem)) {
-        ShaderCompUnit compUnit(
-            FindLanguage(workItem->name),
-            workItem->name,
-            ReadFileData(workItem->name.c_str())
-        );
-
-        if (! compUnit.text) {
+        ShaderCompUnit compUnit(FindLanguage(workItem->name));
+        char* fileText = ReadFileData(workItem->name.c_str());
+        if (fileText == nullptr)
             usage();
-            return;
-        }
-
+        compUnit.addString(workItem->name, fileText);
         compUnits.push_back(compUnit);
     }
 
@@ -828,7 +807,7 @@
     }
 
     for (auto it = compUnits.begin(); it != compUnits.end(); ++it)
-        FreeFileData(it->text);
+        FreeFileData(it->text[0]);
 }
 
 int C_DECL main(int argc, char* argv[])
@@ -978,21 +957,11 @@
 void CompileFile(const char* fileName, ShHandle compiler)
 {
     int ret = 0;
-    char** shaderStrings = ReadFileData(fileName);
-    if (! shaderStrings) {
-        usage();
-    }
-
-    int* lengths = new int[NumShaderStrings];
+    char* shaderString = ReadFileData(fileName);
 
     // move to length-based strings, rather than null-terminated strings
-    for (int s = 0; s < NumShaderStrings; ++s)
-        lengths[s] = (int)strlen(shaderStrings[s]);
-
-    if (! shaderStrings) {
-        CompileFailed = true;
-        return;
-    }
+    int* lengths = new int[1];
+    lengths[0] = (int)strlen(shaderString);
 
     EShMessages messages = EShMsgDefault;
     SetMessageOptions(messages);
@@ -1000,7 +969,7 @@
     for (int i = 0; i < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++i) {
         for (int j = 0; j < ((Options & EOptionMemoryLeakMode) ? 100 : 1); ++j) {
             // ret = ShCompile(compiler, shaderStrings, NumShaderStrings, lengths, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
-            ret = ShCompile(compiler, shaderStrings, NumShaderStrings, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
+            ret = ShCompile(compiler, &shaderString, 1, nullptr, EShOptNone, &Resources, Options, (Options & EOptionDefaultDesktop) ? 110 : 100, false, messages);
             // const char* multi[12] = { "# ve", "rsion", " 300 e", "s", "\n#err",
             //                         "or should be l", "ine 1", "string 5\n", "float glo", "bal",
             //                         ";\n#error should be line 2\n void main() {", "global = 2.3;}" };
@@ -1013,7 +982,7 @@
     }
 
     delete [] lengths;
-    FreeFileData(shaderStrings);
+    FreeFileData(shaderString);
 
     if (ret == 0)
         CompileFailed = true;
@@ -1144,76 +1113,33 @@
 //
 //   Malloc a string of sufficient size and read a string into it.
 //
-char** ReadFileData(const char* fileName)
+char* ReadFileData(const char* fileName)
 {
     FILE *in = nullptr;
     int errorCode = fopen_s(&in, fileName, "r");
-
-    int count = 0;
-    const int maxSourceStrings = 5;  // for testing splitting shader/tokens across multiple strings
-    char** return_data = (char**)malloc(sizeof(char *) * (maxSourceStrings+1)); // freed in FreeFileData()
-
     if (errorCode || in == nullptr)
         Error("unable to open input file");
 
+    int count = 0;
     while (fgetc(in) != EOF)
         count++;
 
     fseek(in, 0, SEEK_SET);
 
-    char *fdata = (char*)malloc(count+2); // freed before return of this function
-    if (! fdata)
-        Error("can't allocate memory");
-
-    if ((int)fread(fdata, 1, count, in) != count) {
-        free(fdata);
+    char* return_data = (char*)malloc(count + 1);  // freed in FreeFileData()
+    if ((int)fread(return_data, 1, count, in) != count) {
+        free(return_data);
         Error("can't read input file");
     }
 
-    fdata[count] = '\0';
+    return_data[count] = '\0';
     fclose(in);
 
-    if (count == 0) {
-        // recover from empty file
-        return_data[0] = (char*)malloc(count+2);  // freed in FreeFileData()
-        return_data[0][0]='\0';
-        NumShaderStrings = 0;
-        free(fdata);
-
-        return return_data;
-    } else
-        NumShaderStrings = 1;  // Set to larger than 1 for testing multiple strings
-
-    // compute how to split up the file into multiple strings, for testing multiple strings
-    int len = (int)(ceil)((float)count/(float)NumShaderStrings);
-    int ptr_len = 0;
-    int i = 0;
-    while (count > 0) {
-        return_data[i] = (char*)malloc(len + 2);  // freed in FreeFileData()
-        memcpy(return_data[i], fdata + ptr_len, len);
-        return_data[i][len] = '\0';
-        count -= len;
-        ptr_len += len;
-        if (count < len) {
-            if (count == 0) {
-               NumShaderStrings = i + 1;
-               break;
-            }
-            len = count;
-        }
-        ++i;
-    }
-
-    free(fdata);
-
     return return_data;
 }
 
-void FreeFileData(char** data)
+void FreeFileData(char* data)
 {
-    for(int i = 0; i < NumShaderStrings; i++)
-        free(data[i]);
-
     free(data);
 }