Add -flimit to glslc to support shader resource limits.

glslc -flimit= ignores language options.
Those aren't really resource limits.  But they do appear
in glslangValidator configuration files.  Ignore them.

Add -flimit-file to read resource limits from a file.

Add --show-limits to show default values, and valid input format.

Add ParseResourceLimits internal function.
diff --git a/CHANGES b/CHANGES
index d0519d3..05d6d96 100644
--- a/CHANGES
+++ b/CHANGES
@@ -7,6 +7,13 @@
    - glslc accepts "-x hlsl", and assumes .hlsl files are HLSL.
    - glslc accepts "-fentry-point=<name>" to set entry point name,
      overriding default value "main".
+ - Support setting shader resource limits in C, C++ APIs, and in
+   glslc
+   - glslc adds -flimit=<setting>
+   - glslc adds --show-limits to display defaults and valid resource
+     limit syntax.
+   - glslc adds "-flimit-file <file>" support to read Glslang resource
+     configuration files, i.e. the output of "glslangValidator -c".
 
 v2016.1 2016-10-12
  - C API for assembling now takes an options object
diff --git a/glslc/CMakeLists.txt b/glslc/CMakeLists.txt
index ba4d4c5..8f21aa2 100644
--- a/glslc/CMakeLists.txt
+++ b/glslc/CMakeLists.txt
@@ -7,6 +7,8 @@
   src/file.h
   src/file_includer.cc
   src/file_includer.h
+  src/resource_parse.h
+  src/resource_parse.cc
   src/shader_stage.cc
   src/shader_stage.h
   src/dependency_info.cc
@@ -31,6 +33,7 @@
   LINK_LIBS glslc shaderc_util shaderc
   TEST_NAMES
     file
+    resource_parse
     stage)
 
 shaderc_add_asciidoc(glslc_doc_README README)
diff --git a/glslc/README.asciidoc b/glslc/README.asciidoc
index a8f22c9..b1551cd 100644
--- a/glslc/README.asciidoc
+++ b/glslc/README.asciidoc
@@ -11,10 +11,15 @@
 == Synopsis
 
 ----
+glslc [--help]
+
+glslc [--show-limits]
+
 glslc [-c|-S|-E]
       [-x ...] [-std=standard]
-      [-fshader-stage=...]
       [-fentry-point=...]
+      [-flimit=...]
+      [-fshader-stage=...]
       [--target-env=...]
       [-g]
       [-O0|-Os]
@@ -110,6 +115,12 @@
 
 `--help` tells the glslc compiler to display all available options and exit.
 
+==== `--show-limits`
+
+`--show-limits` shows default resource limits for shader compilation.  The syntax
+is the same as accepted by `-flimit=` and for the contents of the file specified
+by `-flimit-file`.
+
 ==== `-o`
 
 `-o` lets you specify the output file's name. It cannot be used when there are
@@ -117,6 +128,34 @@
 
 === Language and Mode Selection Options
 
+[[option-f-entry-point]]
+==== `-fentry-point=`
+
+`-fentry-point=<name>` lets you specify the entry point name.  This is only
+significant for HLSL compilation.  The default is "main".
+
+[[option-f-limit]]
+==== `-flimit=`
+
+`-flimit=<resource-limits>` lets you specify resource limits.
+The argument should be a sequence of limit name, integer value pairs.  Tokens
+should be separated by whitespace.  If the same limit is specified several
+times, only the last setting takes effect.
+
+Use `--show-limits` to show the default values, and example syntax.
+
+This option affects all compiled shaders.
+
+[[option-f-limit-file]]
+==== `-flimit-file`
+
+`-flimit-file <resource-limits-file>` lets you specify resource limits in a file.
+The syntax of the file contents is the same as the argument to `-flimit=` and
+the output of `--show-limits`.  This option accepts Glslang resource configuration
+files, e.g. as emitted by `glslangValidator -c`.
+
+This option affects all compiled shaders.
+
 [[option-f-shader-stage]]
 ==== `-fshader-stage=`
 
@@ -151,12 +190,6 @@
 `-fshader-stage=`, since `-fshader-stage=` only affects the treatment of
 subsequent files.
 
-[[option-f-entry-point]]
-==== `-fentry-point=`
-
-`-fentry-point=<name>` lets you specify the entry point name.  This is only
-significant for HLSL compilation.  The default is "main".
-
 ==== `-std=`
 
 `-std=<value>` lets you specify a shader version and profile on the command
diff --git a/glslc/src/main.cc b/glslc/src/main.cc
index 571e65f..108212d 100644
--- a/glslc/src/main.cc
+++ b/glslc/src/main.cc
@@ -21,12 +21,15 @@
 #include <string>
 #include <utility>
 
+#include "libshaderc_util/compiler.h"
+#include "libshaderc_util/io.h"
 #include "libshaderc_util/string_piece.h"
 #include "shaderc/shaderc.h"
 #include "spirv-tools/libspirv.h"
 
 #include "file.h"
 #include "file_compiler.h"
+#include "resource_parse.h"
 #include "shader_stage.h"
 
 using shaderc_util::string_piece;
@@ -46,13 +49,21 @@
   -Dmacro[=defn]    Add an implicit macro definition.
   -E                Outputs only the results of the preprocessing step.
                     Output defaults to standard output.
+  -fentry-point=<name>
+                    Specify the entry point name for HLSL compilation, for
+                    all subsequent source files.  Default is "main".
+  -flimit=<settings>
+                    Specify resource limits. Each limit is specified by a limit
+                    name followed by an integer value.  Tokens should be
+                    separated by whitespace.  If the same limit is specified
+                    several times, only the last setting takes effect.
+  --show-limits     Display available limit names and their default values.
+  -flimit-file <file>
+                    Set limits as specified in the given file.
   -fshader-stage=<stage>
                     Treat subsequent input files as having stage <stage>.
                     Valid stages are vertex, fragment, tesscontrol, tesseval,
                     geometry, and compute.
-  -fentry-point=<name>
-                    Specify the entry point name for HLSL compilation, for
-                    all subsequent source files.  Default is "main".
   -g                Generate source-level debug information.
                     Currently this option has no effect.
   --help            Display available options.
@@ -110,6 +121,22 @@
   }
 }
 
+// Sets resource limits according to the given string. The string
+// should be formated as required for ParseResourceSettings.
+// Returns true on success.  Otherwise returns false and sets err
+// to a descriptive error message.
+bool SetResourceLimits(const std::string& str, shaderc::CompileOptions* options,
+                       std::string* err) {
+  std::vector<glslc::ResourceSetting> settings;
+  if (!ParseResourceSettings(str, &settings, err)) {
+    return false;
+  }
+  for (const auto& setting : settings) {
+    options->SetLimit(setting.limit, setting.value);
+  }
+  return true;
+}
+
 const char kBuildVersion[] =
 #include "build-version.inc"
     ;
@@ -131,6 +158,20 @@
     if (arg == "--help") {
       ::PrintHelp(&std::cout);
       return 0;
+    } else if (arg == "--show-limits") {
+      shaderc_util::Compiler default_compiler;
+// The static cast here depends on us keeping the shaderc_limit enum in
+// lockstep with the shaderc_util::Compiler::Limit enum.  The risk of mismatch
+// is low since both are generated from the same resources.inc file.
+#define RESOURCE(NAME, FIELD, ENUM)                            \
+  std::cout << #NAME << " "                                    \
+            << default_compiler.GetLimit(                      \
+                   static_cast<shaderc_util::Compiler::Limit>( \
+                       shaderc_limit_##ENUM))                  \
+            << std::endl;
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+      return 0;
     } else if (arg == "--version") {
       std::cout << kBuildVersion << std::endl;
       std::cout << "Target: " << spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0)
@@ -156,6 +197,34 @@
     } else if (arg.starts_with("-fentry-point=")) {
       current_entry_point_name =
           arg.substr(std::strlen("-fentry-point=")).str();
+    } else if (arg.starts_with("-flimit=")) {
+      std::string err;
+      if (!SetResourceLimits(arg.substr(std::strlen("-flimit=")).str(),
+                             &compiler.options(), &err)) {
+        std::cerr << "glslc: error: -flimit error: " << err << std::endl;
+        return 1;
+      }
+    } else if (arg.starts_with("-flimit-file")) {
+      std::string err;
+      string_piece limits_file;
+      if (!GetOptionArgument(argc, argv, &i, "-flimit-file", &limits_file)) {
+        std::cerr << "glslc: error: argument to '-flimit-file' is missing"
+                  << std::endl;
+        return 1;
+      }
+      std::vector<char> contents;
+      if (!shaderc_util::ReadFile(limits_file.str(), &contents)) {
+        std::cerr << "glslc: cannot read limits file: " << limits_file
+                  << std::endl;
+        return 1;
+      }
+      if (!SetResourceLimits(
+              string_piece(contents.data(), contents.data() + contents.size())
+                  .str(),
+              &compiler.options(), &err)) {
+        std::cerr << "glslc: error: -flimit-file error: " << err << std::endl;
+        return 1;
+      }
     } else if (arg.starts_with("-std=")) {
       const string_piece standard = arg.substr(std::strlen("-std="));
       int version;
diff --git a/glslc/src/resource_parse.cc b/glslc/src/resource_parse.cc
new file mode 100644
index 0000000..7109333
--- /dev/null
+++ b/glslc/src/resource_parse.cc
@@ -0,0 +1,97 @@
+// Copyright 2016 The Shaderc Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "resource_parse.h"
+
+#include <algorithm>
+#include <cstring>
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+namespace {
+
+// Converts a limit string to a limit enum.  Returns true on successful
+// conversion.
+bool StringToLimit(const std::string& str, shaderc_limit* limit) {
+  const char* cstr = str.c_str();
+#define RESOURCE(NAME, FIELD, ENUM)    \
+  if (0 == std::strcmp(#NAME, cstr)) { \
+    *limit = shaderc_limit_##ENUM;     \
+    return true;                       \
+  }
+#include "libshaderc_util/resources.inc"
+#undef RESOURCE
+  return false;
+}
+
+// Returns true if we should ignore the setting.
+bool IgnoreSetting(const std::string& str) {
+  const std::string ignore_list[] = {
+      "nonInductiveForLoops",
+      "whileLoops",
+      "doWhileLoops",
+      "generalUniformIndexing",
+      "generalAttributeMatrixVectorIndexing",
+      "generalVaryingIndexing",
+      "generalSamplerIndexing",
+      "generalVariableIndexing",
+      "generalConstantMatrixVectorIndexing",
+  };
+  return std::find(std::begin(ignore_list), std::end(ignore_list), str) !=
+         std::end(ignore_list);
+}
+
+}  //  anonymous namespace
+
+namespace glslc {
+
+bool ParseResourceSettings(const std::string& input,
+                           std::vector<ResourceSetting>* limits,
+                           std::string* err) {
+  auto failure = [err, limits](std::string msg) {
+    *err = msg;
+    limits->clear();
+    return false;
+  };
+  std::istringstream input_stream(input);
+  std::istream_iterator<std::string> pos((input_stream));
+  limits->clear();
+
+  while (pos != std::istream_iterator<std::string>()) {
+    const std::string limit_name = *pos++;
+    shaderc_limit limit = static_cast<shaderc_limit>(0);
+    bool ignore = IgnoreSetting(limit_name);
+    if (!ignore) {
+      if (!StringToLimit(limit_name, &limit))
+        return failure(std::string("invalid resource limit: " + limit_name));
+    }
+
+    if (pos == std::istream_iterator<std::string>())
+      return failure(std::string("missing value after limit: ") + limit_name);
+
+    const std::string value_str = *pos;
+    int value;
+    std::istringstream value_stream(value_str);
+    value_stream >> value;
+    if (value_stream.bad() || !value_stream.eof() || value_stream.fail())
+      return failure(std::string("invalid integer: ") + value_str);
+
+    if (!ignore) limits->push_back({limit, value});
+    ++pos;
+  }
+
+  return true;
+}
+}  // anonymous namespace
diff --git a/glslc/src/resource_parse.h b/glslc/src/resource_parse.h
new file mode 100644
index 0000000..9794ce4
--- /dev/null
+++ b/glslc/src/resource_parse.h
@@ -0,0 +1,60 @@
+// Copyright 2016 The Shaderc Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef GLSLC_RESOURCE_PARSE_H
+#define GLSLC_RESOURCE_PARSE_H
+
+#include <string>
+#include <vector>
+
+#include "shaderc/shaderc.h"
+
+namespace glslc {
+
+// A resource limit setting.
+struct ResourceSetting {
+  shaderc_limit limit;
+  int value;
+};
+
+
+// Returns true when two resource setting structures are equal.
+inline bool operator==(const ResourceSetting& lhs, const ResourceSetting& rhs) {
+  return (lhs.limit == rhs.limit) && (lhs.value == rhs.value);
+}
+
+
+// Parses a resource limit setting string.  On success, returns true and populates
+// the limits parameter.  On failure returns failure and emits a message to err.
+// The setting string should be a seqeuence of pairs, where each pair
+// is a limit name followed by a decimal integer.  Tokens should be separated
+// by whitespace.  In particular, this function accepts Glslang's configuration
+// file syntax.  If a limit is mentioned multiple times, then the last setting
+// takes effect.  Ignore settings for:
+//   nonInductiveForLoops
+//   whileLoops
+//   doWhileLoops
+//   generalUniformIndexing
+//   generalAttributeMatrixVectorIndexing
+//   generalVaryingIndexing
+//   generalSamplerIndexing
+//   generalVariableIndexing
+//   generalConstantMatrixVectorIndexing
+bool ParseResourceSettings(const std::string& input,
+                           std::vector<ResourceSetting>* limits,
+                           std::string* err);
+}  // namespace glslc
+
+
+#endif  // GLSLC_FILE_H_
diff --git a/glslc/src/resource_parse_test.cc b/glslc/src/resource_parse_test.cc
new file mode 100644
index 0000000..42c877b
--- /dev/null
+++ b/glslc/src/resource_parse_test.cc
@@ -0,0 +1,75 @@
+// Copyright 2017 The Shaderc Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "resource_parse.h"
+
+#include <gmock/gmock.h>
+
+namespace {
+
+using glslc::ParseResourceSettings;
+using glslc::ResourceSetting;
+using testing::Eq;
+
+struct ResourceSettingsCase {
+  std::string input;
+  bool success;
+  std::vector<ResourceSetting> settings;
+  std::string message;
+};
+
+using ParseResourceSettingsTest = ::testing::TestWithParam<ResourceSettingsCase>;
+
+TEST_P(ParseResourceSettingsTest, Sample) {
+  std::vector<ResourceSetting> settings;
+  std::string err;
+  const bool succeeded = ParseResourceSettings(GetParam().input, &settings, &err);
+  EXPECT_THAT(succeeded, Eq(GetParam().success));
+  EXPECT_THAT(settings, Eq(GetParam().settings));
+  EXPECT_THAT(err, Eq(GetParam().message));
+}
+
+INSTANTIATE_TEST_CASE_P(ParseResources, ParseResourceSettingsTest,
+  ::testing::ValuesIn(std::vector<ResourceSettingsCase>{
+    {"", true, {}, ""},
+    {"   \t \t \n ", true, {}, ""},
+    {" blorp blam", false, {}, "invalid resource limit: blorp"},
+    {"MaxLightsxyz", false, {}, "invalid resource limit: MaxLightsxyz"},
+    {"MaxLights", false, {}, "missing value after limit: MaxLights"},
+    {"MaxLights x", false, {}, "invalid integer: x"},
+    {"MaxLights 99x", false, {}, "invalid integer: 99x"},
+    {"MaxLights 12 blam", false, {}, "invalid resource limit: blam"},
+    {"MaxLights 12", true, {{shaderc_limit_max_lights, 12}}, ""},
+    // Test negative number
+    {"MinProgramTexelOffset -9", true, {{shaderc_limit_min_program_texel_offset, -9}}, ""},
+    // Test leading, intervening, and trailing whitespace
+    {" \tMaxLights \n 12 \t ", true, {{shaderc_limit_max_lights, 12}}, ""},
+    // Test more than one limit setting.
+    {"MinProgramTexelOffset -10 MaxLights 4", true, {{shaderc_limit_min_program_texel_offset, -10}, {shaderc_limit_max_lights, 4}}, ""},
+    // Check ignore cases.
+    {"nonInductiveForLoops", false, {}, "missing value after limit: nonInductiveForLoops"},
+    {"nonInductiveForLoops 1", true, {}, ""},
+    {"whileLoops 1", true, {}, ""},
+    {"doWhileLoops 1", true, {}, ""},
+    {"generalUniformIndexing 1", true, {}, ""},
+    {"generalAttributeMatrixVectorIndexing 1", true, {}, ""},
+    {"generalVaryingIndexing 1", true, {}, ""},
+    {"generalSamplerIndexing 1", true, {}, ""},
+    {"generalVariableIndexing 1", true, {}, ""},
+    {"generalConstantMatrixVectorIndexing 1", true, {}, ""},
+    // Check an ignore case with a regular case
+    {"whileLoops 1 MaxLights 99", true, {{shaderc_limit_max_lights, 99}}, ""},
+  }), );
+
+}  // anonymous namespace
diff --git a/glslc/test/option_flimit.py b/glslc/test/option_flimit.py
new file mode 100644
index 0000000..0fbfd9d
--- /dev/null
+++ b/glslc/test/option_flimit.py
@@ -0,0 +1,136 @@
+# Copyright 2016 The Shaderc Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import expect
+from environment import File, Directory
+from glslc_test_framework import inside_glslc_testsuite
+from placeholder import FileShader
+
+
+def shader_source_with_tex_offset(offset):
+    """Returns a vertex shader using a texture access with the given offset."""
+
+    return """#version 150
+              uniform sampler1D tex;
+              void main() { vec4 x = textureOffset(tex, 1.0, """ + str(offset) + "); }"
+
+
+def shader_with_tex_offset(offset):
+    """Returns a vertex FileShader using a texture access with the given offset."""
+
+    return FileShader(shader_source_with_tex_offset(offset), ".vert")
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitNoEqual(expect.ErrorMessage):
+    """Tests -flimit without equal."""
+
+    glslc_args = ['-flimit']
+    expected_error = ["glslc: error: unknown argument: '-flimit'\n"]
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqual(expect.ValidObjectFile):
+    """Tests -flimit= with no argument."""
+
+    shader = shader_with_tex_offset(0);
+    glslc_args = ['-c', shader, '-flimit=']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqualMaxOffset(expect.ValidObjectFile):
+    """Tests -flimit= with no argument.  The shader uses max offset."""
+
+    shader = shader_with_tex_offset(7);
+    glslc_args = ['-c', shader, '-flimit=']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqualMinOffset(expect.ValidObjectFile):
+    """Tests -flimit= with no argument.  The shader uses min offset."""
+
+    shader = shader_with_tex_offset(-8);
+    glslc_args = ['-c', shader, '-flimit=']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitJustEqualBelowMinOffset(expect.ErrorMessageSubstr):
+    """Tests -flimit= with no argument.  The shader uses below min default offset."""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit=']
+    expected_error_substr = ["'texel offset' : value is out of range"]
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile):
+    """Tests -flimit= with lower than default argument.  The shader uses below min offset."""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 ']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitIgnoredLangFeatureSettingSample(expect.ValidObjectFile):
+    """Tests -flimit= an ignored option."""
+
+    shader = FileShader("#version 150\nvoid main() { while(true); }", '.vert')
+    glslc_args = ['-c', shader, '-flimit=whileLoops 0']
+
+
+@inside_glslc_testsuite('OptionFLimit')
+class TestFLimitLowerThanDefaultMinOffset(expect.ValidObjectFile):
+    """Tests -flimit= with lower than default argument.  The shader uses that offset."""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit= MinProgramTexelOffset -9 ']
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileNoArg(expect.ErrorMessage):
+    """Tests -flimit-file without an argument"""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit-file']
+    expected_error = "glslc: error: argument to '-flimit-file' is missing\n"
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileMissingFile(expect.ErrorMessageSubstr):
+    """Tests -flimit-file without an argument"""
+
+    shader = shader_with_tex_offset(-9);
+    glslc_args = ['-c', shader, '-flimit-file', 'i do not exist']
+    expected_error_substr = "glslc: error: cannot open input file: 'i do not exist'";
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileSetsLowerMinTexelOffset(expect.ValidObjectFile):
+    """Tests -flimit-file with lower than default argument.  The shader uses that offset."""
+
+    limits_file = File('limits.txt', 'MinProgramTexelOffset -9')
+    shader = File('shader.vert', shader_source_with_tex_offset(-9));
+    environment = Directory('.', [limits_file, shader])
+    glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name]
+
+
+@inside_glslc_testsuite('OptionFLimitFile')
+class TestFLimitFileInvalidContents(expect.ErrorMessage):
+    """Tests -flimit-file bad file contents."""
+
+    limits_file = File('limits.txt', 'thisIsBad')
+    shader = File('shader.vert', shader_source_with_tex_offset(-9));
+    environment = Directory('.', [limits_file, shader])
+    glslc_args = ['-c', shader.name, '-flimit-file', limits_file.name]
+    expected_error = 'glslc: error: -flimit-file error: invalid resource limit: thisIsBad\n'
diff --git a/glslc/test/parameter_tests.py b/glslc/test/parameter_tests.py
index cbb6f11..b00d75f 100644
--- a/glslc/test/parameter_tests.py
+++ b/glslc/test/parameter_tests.py
@@ -57,13 +57,21 @@
   -Dmacro[=defn]    Add an implicit macro definition.
   -E                Outputs only the results of the preprocessing step.
                     Output defaults to standard output.
+  -fentry-point=<name>
+                    Specify the entry point name for HLSL compilation, for
+                    all subsequent source files.  Default is "main".
+  -flimit=<settings>
+                    Specify resource limits. Each limit is specified by a limit
+                    name followed by an integer value.  Tokens should be
+                    separated by whitespace.  If the same limit is specified
+                    several times, only the last setting takes effect.
+  --show-limits     Display available limit names and their default values.
+  -flimit-file <file>
+                    Set limits as specified in the given file.
   -fshader-stage=<stage>
                     Treat subsequent input files as having stage <stage>.
                     Valid stages are vertex, fragment, tesscontrol, tesseval,
                     geometry, and compute.
-  -fentry-point=<name>
-                    Specify the entry point name for HLSL compilation, for
-                    all subsequent source files.  Default is "main".
   -g                Generate source-level debug information.
                     Currently this option has no effect.
   --help            Display available options.
@@ -182,3 +190,96 @@
     expected_stderr = [
         "glslc: error: '-': -fshader-stage required when input is from "
         'standard input "-"\n']
+
+
+@inside_glslc_testsuite('Parameters')
+class LimitsHelp(expect.StdoutMatch, expect.StderrMatch):
+    """Tests --show-limits shows correct output."""
+
+    glslc_args = ['--show-limits']
+
+    expected_stderr = ''
+    expected_stdout = """MaxLights 8
+MaxClipPlanes 6
+MaxTextureUnits 2
+MaxTextureCoords 8
+MaxVertexAttribs 16
+MaxVertexUniformComponents 4096
+MaxVaryingFloats 60
+MaxVertexTextureImageUnits 16
+MaxCombinedTextureImageUnits 80
+MaxTextureImageUnits 16
+MaxFragmentUniformComponents 1024
+MaxDrawBuffers 2
+MaxVertexUniformVectors 256
+MaxVaryingVectors 15
+MaxFragmentUniformVectors 256
+MaxVertexOutputVectors 16
+MaxFragmentInputVectors 15
+MinProgramTexelOffset -8
+MaxProgramTexelOffset 7
+MaxClipDistances 8
+MaxComputeWorkGroupCountX 65535
+MaxComputeWorkGroupCountY 65535
+MaxComputeWorkGroupCountZ 65535
+MaxComputeWorkGroupSizeX 1024
+MaxComputeWorkGroupSizeY 1024
+MaxComputeWorkGroupSizeZ 64
+MaxComputeUniformComponents 512
+MaxComputeTextureImageUnits 16
+MaxComputeImageUniforms 8
+MaxComputeAtomicCounters 8
+MaxComputeAtomicCounterBuffers 1
+MaxVaryingComponents 60
+MaxVertexOutputComponents 64
+MaxGeometryInputComponents 64
+MaxGeometryOutputComponents 128
+MaxFragmentInputComponents 128
+MaxImageUnits 8
+MaxCombinedImageUnitsAndFragmentOutputs 8
+MaxCombinedShaderOutputResources 8
+MaxImageSamples 0
+MaxVertexImageUniforms 0
+MaxTessControlImageUniforms 0
+MaxTessEvaluationImageUniforms 0
+MaxGeometryImageUniforms 0
+MaxFragmentImageUniforms 8
+MaxCombinedImageUniforms 8
+MaxGeometryTextureImageUnits 16
+MaxGeometryOutputVertices 256
+MaxGeometryTotalOutputComponents 1024
+MaxGeometryUniformComponents 512
+MaxGeometryVaryingComponents 60
+MaxTessControlInputComponents 128
+MaxTessControlOutputComponents 128
+MaxTessControlTextureImageUnits 16
+MaxTessControlUniformComponents 1024
+MaxTessControlTotalOutputComponents 4096
+MaxTessEvaluationInputComponents 128
+MaxTessEvaluationOutputComponents 128
+MaxTessEvaluationTextureImageUnits 16
+MaxTessEvaluationUniformComponents 1024
+MaxTessPatchComponents 120
+MaxPatchVertices 32
+MaxTessGenLevel 64
+MaxViewports 16
+MaxVertexAtomicCounters 0
+MaxTessControlAtomicCounters 0
+MaxTessEvaluationAtomicCounters 0
+MaxGeometryAtomicCounters 0
+MaxFragmentAtomicCounters 8
+MaxCombinedAtomicCounters 8
+MaxAtomicCounterBindings 1
+MaxVertexAtomicCounterBuffers 0
+MaxTessControlAtomicCounterBuffers 0
+MaxTessEvaluationAtomicCounterBuffers 0
+MaxGeometryAtomicCounterBuffers 0
+MaxFragmentAtomicCounterBuffers 0
+MaxCombinedAtomicCounterBuffers 1
+MaxAtomicCounterBufferSize 32
+MaxTransformFeedbackBuffers 4
+MaxTransformFeedbackInterleavedComponents 64
+MaxCullDistances 8
+MaxCombinedClipAndCullDistances 8
+MaxSamples 4
+"""