Эх сурвалжийг харах

Commit missing files from r251. Sigh.

kenton@google.com 16 жил өмнө
parent
commit
5e744ff961

+ 121 - 0
src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc

@@ -0,0 +1,121 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton):  Share code with the versions of this test in other languages?
+//   It seemed like parameterizing it would add more complexity than it is
+//   worth.
+
+#include <google/protobuf/compiler/cpp/cpp_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+  TestGenerator() {}
+  ~TestGenerator() {}
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        OutputDirectory* output_directory,
+                        string* error) const {
+    TryInsert("test.pb.h", "includes", output_directory);
+    TryInsert("test.pb.h", "namespace_scope", output_directory);
+    TryInsert("test.pb.h", "global_scope", output_directory);
+    TryInsert("test.pb.h", "class_scope:foo.Bar", output_directory);
+    TryInsert("test.pb.h", "class_scope:foo.Bar.Baz", output_directory);
+
+    TryInsert("test.pb.cc", "includes", output_directory);
+    TryInsert("test.pb.cc", "namespace_scope", output_directory);
+    TryInsert("test.pb.cc", "global_scope", output_directory);
+    return true;
+  }
+
+  void TryInsert(const string& filename, const string& insertion_point,
+                 OutputDirectory* output_directory) const {
+    scoped_ptr<io::ZeroCopyOutputStream> output(
+      output_directory->OpenForInsert(filename, insertion_point));
+    io::Printer printer(output.get(), '$');
+    printer.Print("// inserted $name$\n", "name", insertion_point);
+  }
+};
+
+// This test verifies that all the expected insertion points exist.  It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(CppPluginTest, PluginTest) {
+  File::WriteStringToFileOrDie(
+      "syntax = \"proto2\";\n"
+      "package foo;\n"
+      "message Bar {\n"
+      "  message Baz {}\n"
+      "}\n",
+      TestTempDir() + "/test.proto");
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  CppGenerator cpp_generator;
+  TestGenerator test_generator;
+  cli.RegisterGenerator("--cpp_out", &cpp_generator, "");
+  cli.RegisterGenerator("--test_out", &test_generator, "");
+
+  string proto_path = "-I" + TestTempDir();
+  string cpp_out = "--cpp_out=" + TestTempDir();
+  string test_out = "--test_out=" + TestTempDir();
+
+  const char* argv[] = {
+    "protoc",
+    proto_path.c_str(),
+    cpp_out.c_str(),
+    test_out.c_str(),
+    "test.proto"
+  };
+
+  EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+}  // namespace
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

+ 119 - 0
src/google/protobuf/compiler/java/java_plugin_unittest.cc

@@ -0,0 +1,119 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton):  Share code with the versions of this test in other languages?
+//   It seemed like parameterizing it would add more complexity than it is
+//   worth.
+
+#include <google/protobuf/compiler/java/java_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+  TestGenerator() {}
+  ~TestGenerator() {}
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        OutputDirectory* output_directory,
+                        string* error) const {
+    TryInsert("Test.java", "outer_class_scope", output_directory);
+    TryInsert("Test.java", "class_scope:foo.Bar", output_directory);
+    TryInsert("Test.java", "class_scope:foo.Bar.Baz", output_directory);
+    TryInsert("Test.java", "enum_scope:foo.Qux", output_directory);
+    return true;
+  }
+
+  void TryInsert(const string& filename, const string& insertion_point,
+                 OutputDirectory* output_directory) const {
+    scoped_ptr<io::ZeroCopyOutputStream> output(
+      output_directory->OpenForInsert(filename, insertion_point));
+    io::Printer printer(output.get(), '$');
+    printer.Print("// inserted $name$\n", "name", insertion_point);
+  }
+};
+
+// This test verifies that all the expected insertion points exist.  It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(JavaPluginTest, PluginTest) {
+  File::WriteStringToFileOrDie(
+      "syntax = \"proto2\";\n"
+      "package foo;\n"
+      "option java_package = \"\";\n"
+      "option java_outer_classname = \"Test\";\n"
+      "message Bar {\n"
+      "  message Baz {}\n"
+      "}\n"
+      "enum Qux { BLAH = 1; }\n",
+      TestTempDir() + "/test.proto");
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  JavaGenerator java_generator;
+  TestGenerator test_generator;
+  cli.RegisterGenerator("--java_out", &java_generator, "");
+  cli.RegisterGenerator("--test_out", &test_generator, "");
+
+  string proto_path = "-I" + TestTempDir();
+  string java_out = "--java_out=" + TestTempDir();
+  string test_out = "--test_out=" + TestTempDir();
+
+  const char* argv[] = {
+    "protoc",
+    proto_path.c_str(),
+    java_out.c_str(),
+    test_out.c_str(),
+    "test.proto"
+  };
+
+  EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+}  // namespace
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

+ 207 - 0
src/google/protobuf/compiler/mock_code_generator.cc

@@ -0,0 +1,207 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/mock_code_generator.h>
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util-inl.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+static const char* kFirstInsertionPointName = "first_mock_insertion_point";
+static const char* kSecondInsertionPointName = "second_mock_insertion_point";
+static const char* kFirstInsertionPoint =
+    "# @@protoc_insertion_point(first_mock_insertion_point) is here\n";
+static const char* kSecondInsertionPoint =
+    "# @@protoc_insertion_point(second_mock_insertion_point) is here\n";
+
+MockCodeGenerator::MockCodeGenerator(const string& name)
+    : name_(name) {}
+
+MockCodeGenerator::~MockCodeGenerator() {}
+
+void MockCodeGenerator::ExpectGenerated(
+    const string& name,
+    const string& parameter,
+    const string& insertions,
+    const string& file,
+    const string& first_message_name,
+    const string& output_directory) {
+  string content;
+  ASSERT_TRUE(File::ReadFileToString(
+      output_directory + "/" + GetOutputFileName(name, file), &content));
+
+  vector<string> lines;
+  SplitStringUsing(content, "\n", &lines);
+
+  while (!lines.empty() && lines.back().empty()) {
+    lines.pop_back();
+  }
+  for (int i = 0; i < lines.size(); i++) {
+    lines[i] += "\n";
+  }
+
+  vector<string> insertion_list;
+  if (!insertions.empty()) {
+    SplitStringUsing(insertions, ",", &insertion_list);
+  }
+
+  ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2);
+  EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_message_name),
+            lines[0]);
+
+  EXPECT_EQ(kFirstInsertionPoint, lines[1 + insertion_list.size()]);
+  EXPECT_EQ(kSecondInsertionPoint, lines[2 + insertion_list.size() * 2]);
+
+  for (int i = 0; i < insertion_list.size(); i++) {
+    EXPECT_EQ(GetOutputFileContent(insertion_list[i], "first_insert",
+                                   file, first_message_name),
+              lines[1 + i]);
+    EXPECT_EQ(GetOutputFileContent(insertion_list[i], "second_insert",
+                                   file, first_message_name),
+              lines[2 + insertion_list.size() + i]);
+  }
+}
+
+bool MockCodeGenerator::Generate(
+    const FileDescriptor* file,
+    const string& parameter,
+    OutputDirectory* output_directory,
+    string* error) const {
+  for (int i = 0; i < file->message_type_count(); i++) {
+    if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
+      string command = StripPrefixString(file->message_type(i)->name(),
+                                         "MockCodeGenerator_");
+      if (command == "Error") {
+        *error = "Saw message type MockCodeGenerator_Error.";
+        return false;
+      } else if (command == "Exit") {
+        cerr << "Saw message type MockCodeGenerator_Exit." << endl;
+        exit(123);
+      } else if (command == "Abort") {
+        cerr << "Saw message type MockCodeGenerator_Abort." << endl;
+        abort();
+      } else {
+        GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command;
+      }
+    }
+  }
+
+  if (HasPrefixString(parameter, "insert=")) {
+    vector<string> insert_into;
+    SplitStringUsing(StripPrefixString(parameter, "insert="),
+                     ",", &insert_into);
+
+    for (int i = 0; i < insert_into.size(); i++) {
+      {
+        scoped_ptr<io::ZeroCopyOutputStream> output(
+            output_directory->OpenForInsert(
+              GetOutputFileName(insert_into[i], file),
+              kFirstInsertionPointName));
+        io::Printer printer(output.get(), '$');
+        printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file));
+        if (printer.failed()) {
+          *error = "MockCodeGenerator detected write error.";
+          return false;
+        }
+      }
+
+      {
+        scoped_ptr<io::ZeroCopyOutputStream> output(
+            output_directory->OpenForInsert(
+              GetOutputFileName(insert_into[i], file),
+              kSecondInsertionPointName));
+        io::Printer printer(output.get(), '$');
+        printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file));
+        if (printer.failed()) {
+          *error = "MockCodeGenerator detected write error.";
+          return false;
+        }
+      }
+    }
+  } else {
+    scoped_ptr<io::ZeroCopyOutputStream> output(
+        output_directory->Open(GetOutputFileName(name_, file)));
+
+    io::Printer printer(output.get(), '$');
+    printer.PrintRaw(GetOutputFileContent(name_, parameter, file));
+    printer.PrintRaw(kFirstInsertionPoint);
+    printer.PrintRaw(kSecondInsertionPoint);
+
+    if (printer.failed()) {
+      *error = "MockCodeGenerator detected write error.";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+string MockCodeGenerator::GetOutputFileName(const string& generator_name,
+                                            const FileDescriptor* file) {
+  return GetOutputFileName(generator_name, file->name());
+}
+
+string MockCodeGenerator::GetOutputFileName(const string& generator_name,
+                                            const string& file) {
+  return file + ".MockCodeGenerator." + generator_name;
+}
+
+string MockCodeGenerator::GetOutputFileContent(const string& generator_name,
+                                               const string& parameter,
+                                               const FileDescriptor* file) {
+  return GetOutputFileContent(
+      generator_name, parameter, file->name(),
+      file->message_type_count() > 0 ?
+          file->message_type(0)->name() : "(none)");
+}
+
+string MockCodeGenerator::GetOutputFileContent(
+    const string& generator_name,
+    const string& parameter,
+    const string& file,
+    const string& first_message_name) {
+  return strings::Substitute("$0: $1, $2, $3\n",
+      generator_name, parameter, file, first_message_name);
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

+ 108 - 0
src/google/protobuf/compiler/mock_code_generator.h

@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// A mock CodeGenerator, used by command_line_interface_unittest.  This is in
+// its own file so that it can be used both directly and as a plugin.
+//
+// Generate() produces some output which can be checked by ExpectCalled().  The
+// generator can run in a different process (e.g. a plugin).
+//
+// If the parameter is "insert=NAMES", the MockCodeGenerator will insert lines
+// into the files generated by other MockCodeGenerators instead of creating
+// its own file.  NAMES is a comma-separated list of the names of those other
+// MockCodeGenerators.
+//
+// MockCodeGenerator will also modify its behavior slightly if the input file
+// contains a message type with one of the following names:
+//   MockCodeGenerator_Error:  Causes Generate() to return false and set the
+//     error message to "Saw message type MockCodeGenerator_Error."
+//   MockCodeGenerator_Exit:  Generate() prints "Saw message type
+//     MockCodeGenerator_Exit." to stderr and then calls exit(123).
+//   MockCodeGenerator_Abort:  Generate() prints "Saw message type
+//     MockCodeGenerator_Abort." to stderr and then calls abort().
+class MockCodeGenerator : public CodeGenerator {
+ public:
+  MockCodeGenerator(const string& name);
+  virtual ~MockCodeGenerator();
+
+  // Expect (via gTest) that a MockCodeGenerator with the given name was called
+  // with the given parameters by inspecting the output location.
+  //
+  // |insertions| is a comma-separated list of names of MockCodeGenerators which
+  // should have inserted lines into this file.
+  static void ExpectGenerated(const string& name,
+                              const string& parameter,
+                              const string& insertions,
+                              const string& file,
+                              const string& first_message_name,
+                              const string& output_directory);
+
+  // Get the name of the file which would be written by the given generator.
+  static string GetOutputFileName(const string& generator_name,
+                                  const FileDescriptor* file);
+  static string GetOutputFileName(const string& generator_name,
+                                  const string& file);
+
+  // implements CodeGenerator ----------------------------------------
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        OutputDirectory* output_directory,
+                        string* error) const;
+
+ private:
+  string name_;
+
+  static string GetOutputFileContent(const string& generator_name,
+                                     const string& parameter,
+                                     const FileDescriptor* file);
+  static string GetOutputFileContent(const string& generator_name,
+                                     const string& parameter,
+                                     const string& file,
+                                     const string& first_message_name);
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_MOCK_CODE_GENERATOR_H__

+ 135 - 0
src/google/protobuf/compiler/plugin.cc

@@ -0,0 +1,135 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/plugin.h>
+
+#include <iostream>
+#include <set>
+#include <unistd.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/plugin.pb.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class GeneratorResponseOutputDirectory : public OutputDirectory {
+ public:
+  GeneratorResponseOutputDirectory(CodeGeneratorResponse* response)
+      : response_(response) {}
+  virtual ~GeneratorResponseOutputDirectory() {}
+
+  // implements OutputDirectory --------------------------------------
+
+  virtual io::ZeroCopyOutputStream* Open(const string& filename) {
+    CodeGeneratorResponse::File* file = response_->add_file();
+    file->set_name(filename);
+    return new io::StringOutputStream(file->mutable_content());
+  }
+
+  virtual io::ZeroCopyOutputStream* OpenForInsert(
+      const string& filename, const string& insertion_point) {
+    CodeGeneratorResponse::File* file = response_->add_file();
+    file->set_name(filename);
+    file->set_insertion_point(insertion_point);
+    return new io::StringOutputStream(file->mutable_content());
+  }
+
+ private:
+  CodeGeneratorResponse* response_;
+};
+
+int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
+
+  if (argc > 1) {
+    cerr << argv[0] << ": Unknown option: " << argv[1] << endl;
+    return 1;
+  }
+
+  CodeGeneratorRequest request;
+  if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
+    cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl;
+    return 1;
+  }
+
+  DescriptorPool pool;
+  for (int i = 0; i < request.proto_file_size(); i++) {
+    const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
+    if (file == NULL) {
+      // BuildFile() already wrote an error message.
+      return 1;
+    }
+  }
+
+  CodeGeneratorResponse response;
+  GeneratorResponseOutputDirectory output_directory(&response);
+
+  for (int i = 0; i < request.file_to_generate_size(); i++) {
+    const FileDescriptor* file =
+        pool.FindFileByName(request.file_to_generate(i));
+    if (file == NULL) {
+      cerr << argv[0] << ": protoc asked plugin to generate a file but "
+              "did not provide a descriptor for the file: "
+           << request.file_to_generate(i) << endl;
+      return 1;
+    }
+
+    string error;
+    bool succeeded = generator->Generate(
+        file, request.parameter(), &output_directory, &error);
+
+    if (!succeeded && error.empty()) {
+      error = "Code generator returned false but provided no error "
+              "description.";
+    }
+    if (!error.empty()) {
+      response.set_error(file->name() + ": " + error);
+      break;
+    }
+  }
+
+  if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
+    cerr << argv[0] << ": Error writing to stdout." << endl;
+    return 1;
+  }
+
+  return 0;
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

+ 56 - 0
src/google/protobuf/compiler/plugin.h

@@ -0,0 +1,56 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+#define GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class CodeGenerator;    // code_generator.h
+
+// To implement a protoc plugin in C++, simply write an implementation of
+// CodeGenerator, then create a main() function like:
+//   int main(int argc, char* argv[]) {
+//     MyCodeGenerator generator;
+//     return PluginMain(argc, argv, &generator);
+//   }
+int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__

+ 1084 - 0
src/google/protobuf/compiler/plugin.pb.cc

@@ -0,0 +1,1084 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "google/protobuf/compiler/plugin.pb.h"
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+namespace {
+
+const ::google::protobuf::Descriptor* CodeGeneratorRequest_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  CodeGeneratorRequest_reflection_ = NULL;
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  CodeGeneratorResponse_reflection_ = NULL;
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_File_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  CodeGeneratorResponse_File_reflection_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+  protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "google/protobuf/compiler/plugin.proto");
+  GOOGLE_CHECK(file != NULL);
+  CodeGeneratorRequest_descriptor_ = file->message_type(0);
+  static const int CodeGeneratorRequest_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, file_to_generate_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, parameter_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, proto_file_),
+  };
+  CodeGeneratorRequest_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      CodeGeneratorRequest_descriptor_,
+      CodeGeneratorRequest::default_instance_,
+      CodeGeneratorRequest_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorRequest, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(CodeGeneratorRequest));
+  CodeGeneratorResponse_descriptor_ = file->message_type(1);
+  static const int CodeGeneratorResponse_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, error_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, file_),
+  };
+  CodeGeneratorResponse_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      CodeGeneratorResponse_descriptor_,
+      CodeGeneratorResponse::default_instance_,
+      CodeGeneratorResponse_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(CodeGeneratorResponse));
+  CodeGeneratorResponse_File_descriptor_ = CodeGeneratorResponse_descriptor_->nested_type(0);
+  static const int CodeGeneratorResponse_File_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, name_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, insertion_point_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, content_),
+  };
+  CodeGeneratorResponse_File_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      CodeGeneratorResponse_File_descriptor_,
+      CodeGeneratorResponse_File::default_instance_,
+      CodeGeneratorResponse_File_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(CodeGeneratorResponse_File, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(CodeGeneratorResponse_File));
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    CodeGeneratorRequest_descriptor_, &CodeGeneratorRequest::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    CodeGeneratorResponse_descriptor_, &CodeGeneratorResponse::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    CodeGeneratorResponse_File_descriptor_, &CodeGeneratorResponse_File::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+  delete CodeGeneratorRequest::default_instance_;
+  delete CodeGeneratorRequest_reflection_;
+  delete CodeGeneratorResponse::default_instance_;
+  delete CodeGeneratorResponse_reflection_;
+  delete CodeGeneratorResponse_File::default_instance_;
+  delete CodeGeneratorResponse_File_reflection_;
+}
+
+void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto();
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n%google/protobuf/compiler/plugin.proto\022"
+    "\030google.protobuf.compiler\032 google/protob"
+    "uf/descriptor.proto\"}\n\024CodeGeneratorRequ"
+    "est\022\030\n\020file_to_generate\030\001 \003(\t\022\021\n\tparamet"
+    "er\030\002 \001(\t\0228\n\nproto_file\030\017 \003(\0132$.google.pr"
+    "otobuf.FileDescriptorProto\"\252\001\n\025CodeGener"
+    "atorResponse\022\r\n\005error\030\001 \001(\t\022B\n\004file\030\017 \003("
+    "\01324.google.protobuf.compiler.CodeGenerat"
+    "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n"
+    "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\t", 399);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes);
+  CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest();
+  CodeGeneratorResponse::default_instance_ = new CodeGeneratorResponse();
+  CodeGeneratorResponse_File::default_instance_ = new CodeGeneratorResponse_File();
+  CodeGeneratorRequest::default_instance_->InitAsDefaultInstance();
+  CodeGeneratorResponse::default_instance_->InitAsDefaultInstance();
+  CodeGeneratorResponse_File::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
+  StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto() {
+    protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  }
+} static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_;
+
+
+// ===================================================================
+
+const ::std::string CodeGeneratorRequest::_default_parameter_;
+#ifndef _MSC_VER
+const int CodeGeneratorRequest::kFileToGenerateFieldNumber;
+const int CodeGeneratorRequest::kParameterFieldNumber;
+const int CodeGeneratorRequest::kProtoFileFieldNumber;
+#endif  // !_MSC_VER
+
+CodeGeneratorRequest::CodeGeneratorRequest()
+  : ::google::protobuf::Message() {
+  SharedCtor();
+}
+
+void CodeGeneratorRequest::InitAsDefaultInstance() {
+}
+
+CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from)
+  : ::google::protobuf::Message() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void CodeGeneratorRequest::SharedCtor() {
+  _cached_size_ = 0;
+  parameter_ = const_cast< ::std::string*>(&_default_parameter_);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorRequest::~CodeGeneratorRequest() {
+  SharedDtor();
+}
+
+void CodeGeneratorRequest::SharedDtor() {
+  if (parameter_ != &_default_parameter_) {
+    delete parameter_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+void CodeGeneratorRequest::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorRequest::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return CodeGeneratorRequest_descriptor_;
+}
+
+const CodeGeneratorRequest& CodeGeneratorRequest::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();  return *default_instance_;
+}
+
+CodeGeneratorRequest* CodeGeneratorRequest::default_instance_ = NULL;
+
+CodeGeneratorRequest* CodeGeneratorRequest::New() const {
+  return new CodeGeneratorRequest;
+}
+
+void CodeGeneratorRequest::Clear() {
+  if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+    if (_has_bit(1)) {
+      if (parameter_ != &_default_parameter_) {
+        parameter_->clear();
+      }
+    }
+  }
+  file_to_generate_.Clear();
+  proto_file_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool CodeGeneratorRequest::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // repeated string file_to_generate = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_file_to_generate:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->add_file_to_generate()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->file_to_generate(0).data(), this->file_to_generate(0).length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(10)) goto parse_file_to_generate;
+        if (input->ExpectTag(18)) goto parse_parameter;
+        break;
+      }
+      
+      // optional string parameter = 2;
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_parameter:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_parameter()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->parameter().data(), this->parameter().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(122)) goto parse_proto_file;
+        break;
+      }
+      
+      // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+      case 15: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_proto_file:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_proto_file()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(122)) goto parse_proto_file;
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void CodeGeneratorRequest::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // repeated string file_to_generate = 1;
+  for (int i = 0; i < this->file_to_generate_size(); i++) {
+  ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+    this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+    ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->file_to_generate(i), output);
+  }
+  
+  // optional string parameter = 2;
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->parameter().data(), this->parameter().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->parameter(), output);
+  }
+  
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  for (int i = 0; i < this->proto_file_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      15, this->proto_file(i), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // repeated string file_to_generate = 1;
+  for (int i = 0; i < this->file_to_generate_size(); i++) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->file_to_generate(i).data(), this->file_to_generate(i).length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteStringToArray(1, this->file_to_generate(i), target);
+  }
+  
+  // optional string parameter = 2;
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->parameter().data(), this->parameter().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->parameter(), target);
+  }
+  
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  for (int i = 0; i < this->proto_file_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        15, this->proto_file(i), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int CodeGeneratorRequest::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+    // optional string parameter = 2;
+    if (has_parameter()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->parameter());
+    }
+    
+  }
+  // repeated string file_to_generate = 1;
+  total_size += 1 * this->file_to_generate_size();
+  for (int i = 0; i < this->file_to_generate_size(); i++) {
+    total_size += ::google::protobuf::internal::WireFormatLite::StringSize(
+      this->file_to_generate(i));
+  }
+  
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  total_size += 1 * this->proto_file_size();
+  for (int i = 0; i < this->proto_file_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->proto_file(i));
+  }
+  
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const CodeGeneratorRequest* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorRequest*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  file_to_generate_.MergeFrom(from.file_to_generate_);
+  proto_file_.MergeFrom(from.proto_file_);
+  if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) {
+    if (from._has_bit(1)) {
+      set_parameter(from.parameter());
+    }
+  }
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void CodeGeneratorRequest::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CodeGeneratorRequest::IsInitialized() const {
+  
+  for (int i = 0; i < proto_file_size(); i++) {
+    if (!this->proto_file(i).IsInitialized()) return false;
+  }
+  return true;
+}
+
+void CodeGeneratorRequest::Swap(CodeGeneratorRequest* other) {
+  if (other != this) {
+    file_to_generate_.Swap(&other->file_to_generate_);
+    std::swap(parameter_, other->parameter_);
+    proto_file_.Swap(&other->proto_file_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata CodeGeneratorRequest::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = CodeGeneratorRequest_descriptor_;
+  metadata.reflection = CodeGeneratorRequest_reflection_;
+  return metadata;
+}
+
+
+// ===================================================================
+
+const ::std::string CodeGeneratorResponse_File::_default_name_;
+const ::std::string CodeGeneratorResponse_File::_default_insertion_point_;
+const ::std::string CodeGeneratorResponse_File::_default_content_;
+#ifndef _MSC_VER
+const int CodeGeneratorResponse_File::kNameFieldNumber;
+const int CodeGeneratorResponse_File::kInsertionPointFieldNumber;
+const int CodeGeneratorResponse_File::kContentFieldNumber;
+#endif  // !_MSC_VER
+
+CodeGeneratorResponse_File::CodeGeneratorResponse_File()
+  : ::google::protobuf::Message() {
+  SharedCtor();
+}
+
+void CodeGeneratorResponse_File::InitAsDefaultInstance() {
+}
+
+CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from)
+  : ::google::protobuf::Message() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse_File::SharedCtor() {
+  _cached_size_ = 0;
+  name_ = const_cast< ::std::string*>(&_default_name_);
+  insertion_point_ = const_cast< ::std::string*>(&_default_insertion_point_);
+  content_ = const_cast< ::std::string*>(&_default_content_);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorResponse_File::~CodeGeneratorResponse_File() {
+  SharedDtor();
+}
+
+void CodeGeneratorResponse_File::SharedDtor() {
+  if (name_ != &_default_name_) {
+    delete name_;
+  }
+  if (insertion_point_ != &_default_insertion_point_) {
+    delete insertion_point_;
+  }
+  if (content_ != &_default_content_) {
+    delete content_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+void CodeGeneratorResponse_File::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorResponse_File::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return CodeGeneratorResponse_File_descriptor_;
+}
+
+const CodeGeneratorResponse_File& CodeGeneratorResponse_File::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();  return *default_instance_;
+}
+
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::default_instance_ = NULL;
+
+CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const {
+  return new CodeGeneratorResponse_File;
+}
+
+void CodeGeneratorResponse_File::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (_has_bit(0)) {
+      if (name_ != &_default_name_) {
+        name_->clear();
+      }
+    }
+    if (_has_bit(1)) {
+      if (insertion_point_ != &_default_insertion_point_) {
+        insertion_point_->clear();
+      }
+    }
+    if (_has_bit(2)) {
+      if (content_ != &_default_content_) {
+        content_->clear();
+      }
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool CodeGeneratorResponse_File::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string name = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_name()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->name().data(), this->name().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(18)) goto parse_insertion_point;
+        break;
+      }
+      
+      // optional string insertion_point = 2;
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_insertion_point:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_insertion_point()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->insertion_point().data(), this->insertion_point().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(122)) goto parse_content;
+        break;
+      }
+      
+      // optional string content = 15;
+      case 15: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_content:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_content()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->content().data(), this->content().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void CodeGeneratorResponse_File::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // optional string name = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->name(), output);
+  }
+  
+  // optional string insertion_point = 2;
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->insertion_point().data(), this->insertion_point().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      2, this->insertion_point(), output);
+  }
+  
+  // optional string content = 15;
+  if (_has_bit(2)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->content().data(), this->content().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      15, this->content(), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // optional string name = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->name().data(), this->name().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->name(), target);
+  }
+  
+  // optional string insertion_point = 2;
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->insertion_point().data(), this->insertion_point().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        2, this->insertion_point(), target);
+  }
+  
+  // optional string content = 15;
+  if (_has_bit(2)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->content().data(), this->content().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        15, this->content(), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int CodeGeneratorResponse_File::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional string name = 1;
+    if (has_name()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->name());
+    }
+    
+    // optional string insertion_point = 2;
+    if (has_insertion_point()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->insertion_point());
+    }
+    
+    // optional string content = 15;
+    if (has_content()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->content());
+    }
+    
+  }
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const CodeGeneratorResponse_File* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse_File*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_name(from.name());
+    }
+    if (from._has_bit(1)) {
+      set_insertion_point(from.insertion_point());
+    }
+    if (from._has_bit(2)) {
+      set_content(from.content());
+    }
+  }
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CodeGeneratorResponse_File::IsInitialized() const {
+  
+  return true;
+}
+
+void CodeGeneratorResponse_File::Swap(CodeGeneratorResponse_File* other) {
+  if (other != this) {
+    std::swap(name_, other->name_);
+    std::swap(insertion_point_, other->insertion_point_);
+    std::swap(content_, other->content_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata CodeGeneratorResponse_File::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = CodeGeneratorResponse_File_descriptor_;
+  metadata.reflection = CodeGeneratorResponse_File_reflection_;
+  return metadata;
+}
+
+
+// -------------------------------------------------------------------
+
+const ::std::string CodeGeneratorResponse::_default_error_;
+#ifndef _MSC_VER
+const int CodeGeneratorResponse::kErrorFieldNumber;
+const int CodeGeneratorResponse::kFileFieldNumber;
+#endif  // !_MSC_VER
+
+CodeGeneratorResponse::CodeGeneratorResponse()
+  : ::google::protobuf::Message() {
+  SharedCtor();
+}
+
+void CodeGeneratorResponse::InitAsDefaultInstance() {
+}
+
+CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from)
+  : ::google::protobuf::Message() {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse::SharedCtor() {
+  _cached_size_ = 0;
+  error_ = const_cast< ::std::string*>(&_default_error_);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+CodeGeneratorResponse::~CodeGeneratorResponse() {
+  SharedDtor();
+}
+
+void CodeGeneratorResponse::SharedDtor() {
+  if (error_ != &_default_error_) {
+    delete error_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+void CodeGeneratorResponse::SetCachedSize(int size) const {
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+}
+const ::google::protobuf::Descriptor* CodeGeneratorResponse::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return CodeGeneratorResponse_descriptor_;
+}
+
+const CodeGeneratorResponse& CodeGeneratorResponse::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();  return *default_instance_;
+}
+
+CodeGeneratorResponse* CodeGeneratorResponse::default_instance_ = NULL;
+
+CodeGeneratorResponse* CodeGeneratorResponse::New() const {
+  return new CodeGeneratorResponse;
+}
+
+void CodeGeneratorResponse::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (_has_bit(0)) {
+      if (error_ != &_default_error_) {
+        error_->clear();
+      }
+    }
+  }
+  file_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool CodeGeneratorResponse::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // optional string error = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+                input, this->mutable_error()));
+          ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+            this->error().data(), this->error().length(),
+            ::google::protobuf::internal::WireFormat::PARSE);
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(122)) goto parse_file;
+        break;
+      }
+      
+      // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+      case 15: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+         parse_file:
+          DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+                input, add_file()));
+        } else {
+          goto handle_uninterpreted;
+        }
+        if (input->ExpectTag(122)) goto parse_file;
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void CodeGeneratorResponse::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  // optional string error = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->error().data(), this->error().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->error(), output);
+  }
+  
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  for (int i = 0; i < this->file_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray(
+      15, this->file(i), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // optional string error = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->error().data(), this->error().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->error(), target);
+  }
+  
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  for (int i = 0; i < this->file_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        15, this->file(i), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int CodeGeneratorResponse::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // optional string error = 1;
+    if (has_error()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->error());
+    }
+    
+  }
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  total_size += 1 * this->file_size();
+  for (int i = 0; i < this->file_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->file(i));
+  }
+  
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
+  _cached_size_ = total_size;
+  GOOGLE_SAFE_CONCURRENT_WRITES_END();
+  return total_size;
+}
+
+void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const CodeGeneratorResponse* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const CodeGeneratorResponse*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  file_.MergeFrom(from.file_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_error(from.error());
+    }
+  }
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void CodeGeneratorResponse::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool CodeGeneratorResponse::IsInitialized() const {
+  
+  return true;
+}
+
+void CodeGeneratorResponse::Swap(CodeGeneratorResponse* other) {
+  if (other != this) {
+    std::swap(error_, other->error_);
+    file_.Swap(&other->file_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata CodeGeneratorResponse::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = CodeGeneratorResponse_descriptor_;
+  metadata.reflection = CodeGeneratorResponse_reflection_;
+  return metadata;
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+// @@protoc_insertion_point(global_scope)

+ 727 - 0
src/google/protobuf/compiler/plugin.pb.h

@@ -0,0 +1,727 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: google/protobuf/compiler/plugin.proto
+
+#ifndef PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+#define PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 2003000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 2003000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include "google/protobuf/descriptor.pb.h"
+// @@protoc_insertion_point(includes)
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+// Internal implementation detail -- do not call these.
+void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+
+class CodeGeneratorRequest;
+class CodeGeneratorResponse;
+class CodeGeneratorResponse_File;
+
+// ===================================================================
+
+class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message {
+ public:
+  CodeGeneratorRequest();
+  virtual ~CodeGeneratorRequest();
+  
+  CodeGeneratorRequest(const CodeGeneratorRequest& from);
+  
+  inline CodeGeneratorRequest& operator=(const CodeGeneratorRequest& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const CodeGeneratorRequest& default_instance();
+  
+  void Swap(CodeGeneratorRequest* other);
+  
+  // implements Message ----------------------------------------------
+  
+  CodeGeneratorRequest* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const CodeGeneratorRequest& from);
+  void MergeFrom(const CodeGeneratorRequest& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  // accessors -------------------------------------------------------
+  
+  // repeated string file_to_generate = 1;
+  inline int file_to_generate_size() const;
+  inline void clear_file_to_generate();
+  static const int kFileToGenerateFieldNumber = 1;
+  inline const ::std::string& file_to_generate(int index) const;
+  inline ::std::string* mutable_file_to_generate(int index);
+  inline void set_file_to_generate(int index, const ::std::string& value);
+  inline void set_file_to_generate(int index, const char* value);
+  inline void set_file_to_generate(int index, const char* value, size_t size);
+  inline ::std::string* add_file_to_generate();
+  inline void add_file_to_generate(const ::std::string& value);
+  inline void add_file_to_generate(const char* value);
+  inline void add_file_to_generate(const char* value, size_t size);
+  inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const;
+  inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate();
+  
+  // optional string parameter = 2;
+  inline bool has_parameter() const;
+  inline void clear_parameter();
+  static const int kParameterFieldNumber = 2;
+  inline const ::std::string& parameter() const;
+  inline void set_parameter(const ::std::string& value);
+  inline void set_parameter(const char* value);
+  inline void set_parameter(const char* value, size_t size);
+  inline ::std::string* mutable_parameter();
+  
+  // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+  inline int proto_file_size() const;
+  inline void clear_proto_file();
+  static const int kProtoFileFieldNumber = 15;
+  inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const;
+  inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index);
+  inline ::google::protobuf::FileDescriptorProto* add_proto_file();
+  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+      proto_file() const;
+  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+      mutable_proto_file();
+  
+  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest)
+ private:
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  mutable int _cached_size_;
+  
+  ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_;
+  ::std::string* parameter_;
+  static const ::std::string _default_parameter_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_;
+  friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static CodeGeneratorRequest* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::Message {
+ public:
+  CodeGeneratorResponse_File();
+  virtual ~CodeGeneratorResponse_File();
+  
+  CodeGeneratorResponse_File(const CodeGeneratorResponse_File& from);
+  
+  inline CodeGeneratorResponse_File& operator=(const CodeGeneratorResponse_File& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const CodeGeneratorResponse_File& default_instance();
+  
+  void Swap(CodeGeneratorResponse_File* other);
+  
+  // implements Message ----------------------------------------------
+  
+  CodeGeneratorResponse_File* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const CodeGeneratorResponse_File& from);
+  void MergeFrom(const CodeGeneratorResponse_File& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  // accessors -------------------------------------------------------
+  
+  // optional string name = 1;
+  inline bool has_name() const;
+  inline void clear_name();
+  static const int kNameFieldNumber = 1;
+  inline const ::std::string& name() const;
+  inline void set_name(const ::std::string& value);
+  inline void set_name(const char* value);
+  inline void set_name(const char* value, size_t size);
+  inline ::std::string* mutable_name();
+  
+  // optional string insertion_point = 2;
+  inline bool has_insertion_point() const;
+  inline void clear_insertion_point();
+  static const int kInsertionPointFieldNumber = 2;
+  inline const ::std::string& insertion_point() const;
+  inline void set_insertion_point(const ::std::string& value);
+  inline void set_insertion_point(const char* value);
+  inline void set_insertion_point(const char* value, size_t size);
+  inline ::std::string* mutable_insertion_point();
+  
+  // optional string content = 15;
+  inline bool has_content() const;
+  inline void clear_content();
+  static const int kContentFieldNumber = 15;
+  inline const ::std::string& content() const;
+  inline void set_content(const ::std::string& value);
+  inline void set_content(const char* value);
+  inline void set_content(const char* value, size_t size);
+  inline ::std::string* mutable_content();
+  
+  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File)
+ private:
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  mutable int _cached_size_;
+  
+  ::std::string* name_;
+  static const ::std::string _default_name_;
+  ::std::string* insertion_point_;
+  static const ::std::string _default_insertion_point_;
+  ::std::string* content_;
+  static const ::std::string _default_content_;
+  friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static CodeGeneratorResponse_File* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Message {
+ public:
+  CodeGeneratorResponse();
+  virtual ~CodeGeneratorResponse();
+  
+  CodeGeneratorResponse(const CodeGeneratorResponse& from);
+  
+  inline CodeGeneratorResponse& operator=(const CodeGeneratorResponse& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const CodeGeneratorResponse& default_instance();
+  
+  void Swap(CodeGeneratorResponse* other);
+  
+  // implements Message ----------------------------------------------
+  
+  CodeGeneratorResponse* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const CodeGeneratorResponse& from);
+  void MergeFrom(const CodeGeneratorResponse& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const;
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef CodeGeneratorResponse_File File;
+  
+  // accessors -------------------------------------------------------
+  
+  // optional string error = 1;
+  inline bool has_error() const;
+  inline void clear_error();
+  static const int kErrorFieldNumber = 1;
+  inline const ::std::string& error() const;
+  inline void set_error(const ::std::string& value);
+  inline void set_error(const char* value);
+  inline void set_error(const char* value, size_t size);
+  inline ::std::string* mutable_error();
+  
+  // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+  inline int file_size() const;
+  inline void clear_file();
+  static const int kFileFieldNumber = 15;
+  inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const;
+  inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index);
+  inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file();
+  inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+      file() const;
+  inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+      mutable_file();
+  
+  // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
+ private:
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  mutable int _cached_size_;
+  
+  ::std::string* error_;
+  static const ::std::string _default_error_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_;
+  friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static CodeGeneratorResponse* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+// CodeGeneratorRequest
+
+// repeated string file_to_generate = 1;
+inline int CodeGeneratorRequest::file_to_generate_size() const {
+  return file_to_generate_.size();
+}
+inline void CodeGeneratorRequest::clear_file_to_generate() {
+  file_to_generate_.Clear();
+}
+inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const {
+  return file_to_generate_.Get(index);
+}
+inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) {
+  return file_to_generate_.Mutable(index);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) {
+  file_to_generate_.Mutable(index)->assign(value);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) {
+  file_to_generate_.Mutable(index)->assign(value);
+}
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+  file_to_generate_.Mutable(index)->assign(
+    reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorRequest::add_file_to_generate() {
+  return file_to_generate_.Add();
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) {
+  file_to_generate_.Add()->assign(value);
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
+  file_to_generate_.Add()->assign(value);
+}
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+  file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
+}
+inline const ::google::protobuf::RepeatedPtrField< ::std::string>&
+CodeGeneratorRequest::file_to_generate() const {
+  return file_to_generate_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::std::string>*
+CodeGeneratorRequest::mutable_file_to_generate() {
+  return &file_to_generate_;
+}
+
+// optional string parameter = 2;
+inline bool CodeGeneratorRequest::has_parameter() const {
+  return _has_bit(1);
+}
+inline void CodeGeneratorRequest::clear_parameter() {
+  if (parameter_ != &_default_parameter_) {
+    parameter_->clear();
+  }
+  _clear_bit(1);
+}
+inline const ::std::string& CodeGeneratorRequest::parameter() const {
+  return *parameter_;
+}
+inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) {
+  _set_bit(1);
+  if (parameter_ == &_default_parameter_) {
+    parameter_ = new ::std::string;
+  }
+  parameter_->assign(value);
+}
+inline void CodeGeneratorRequest::set_parameter(const char* value) {
+  _set_bit(1);
+  if (parameter_ == &_default_parameter_) {
+    parameter_ = new ::std::string;
+  }
+  parameter_->assign(value);
+}
+inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) {
+  _set_bit(1);
+  if (parameter_ == &_default_parameter_) {
+    parameter_ = new ::std::string;
+  }
+  parameter_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorRequest::mutable_parameter() {
+  _set_bit(1);
+  if (parameter_ == &_default_parameter_) {
+    parameter_ = new ::std::string;
+  }
+  return parameter_;
+}
+
+// repeated .google.protobuf.FileDescriptorProto proto_file = 15;
+inline int CodeGeneratorRequest::proto_file_size() const {
+  return proto_file_.size();
+}
+inline void CodeGeneratorRequest::clear_proto_file() {
+  proto_file_.Clear();
+}
+inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const {
+  return proto_file_.Get(index);
+}
+inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) {
+  return proto_file_.Mutable(index);
+}
+inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() {
+  return proto_file_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >&
+CodeGeneratorRequest::proto_file() const {
+  return proto_file_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >*
+CodeGeneratorRequest::mutable_proto_file() {
+  return &proto_file_;
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse_File
+
+// optional string name = 1;
+inline bool CodeGeneratorResponse_File::has_name() const {
+  return _has_bit(0);
+}
+inline void CodeGeneratorResponse_File::clear_name() {
+  if (name_ != &_default_name_) {
+    name_->clear();
+  }
+  _clear_bit(0);
+}
+inline const ::std::string& CodeGeneratorResponse_File::name() const {
+  return *name_;
+}
+inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) {
+  _set_bit(0);
+  if (name_ == &_default_name_) {
+    name_ = new ::std::string;
+  }
+  name_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_name(const char* value) {
+  _set_bit(0);
+  if (name_ == &_default_name_) {
+    name_ = new ::std::string;
+  }
+  name_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) {
+  _set_bit(0);
+  if (name_ == &_default_name_) {
+    name_ = new ::std::string;
+  }
+  name_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_name() {
+  _set_bit(0);
+  if (name_ == &_default_name_) {
+    name_ = new ::std::string;
+  }
+  return name_;
+}
+
+// optional string insertion_point = 2;
+inline bool CodeGeneratorResponse_File::has_insertion_point() const {
+  return _has_bit(1);
+}
+inline void CodeGeneratorResponse_File::clear_insertion_point() {
+  if (insertion_point_ != &_default_insertion_point_) {
+    insertion_point_->clear();
+  }
+  _clear_bit(1);
+}
+inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const {
+  return *insertion_point_;
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) {
+  _set_bit(1);
+  if (insertion_point_ == &_default_insertion_point_) {
+    insertion_point_ = new ::std::string;
+  }
+  insertion_point_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) {
+  _set_bit(1);
+  if (insertion_point_ == &_default_insertion_point_) {
+    insertion_point_ = new ::std::string;
+  }
+  insertion_point_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) {
+  _set_bit(1);
+  if (insertion_point_ == &_default_insertion_point_) {
+    insertion_point_ = new ::std::string;
+  }
+  insertion_point_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() {
+  _set_bit(1);
+  if (insertion_point_ == &_default_insertion_point_) {
+    insertion_point_ = new ::std::string;
+  }
+  return insertion_point_;
+}
+
+// optional string content = 15;
+inline bool CodeGeneratorResponse_File::has_content() const {
+  return _has_bit(2);
+}
+inline void CodeGeneratorResponse_File::clear_content() {
+  if (content_ != &_default_content_) {
+    content_->clear();
+  }
+  _clear_bit(2);
+}
+inline const ::std::string& CodeGeneratorResponse_File::content() const {
+  return *content_;
+}
+inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) {
+  _set_bit(2);
+  if (content_ == &_default_content_) {
+    content_ = new ::std::string;
+  }
+  content_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_content(const char* value) {
+  _set_bit(2);
+  if (content_ == &_default_content_) {
+    content_ = new ::std::string;
+  }
+  content_->assign(value);
+}
+inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) {
+  _set_bit(2);
+  if (content_ == &_default_content_) {
+    content_ = new ::std::string;
+  }
+  content_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse_File::mutable_content() {
+  _set_bit(2);
+  if (content_ == &_default_content_) {
+    content_ = new ::std::string;
+  }
+  return content_;
+}
+
+// -------------------------------------------------------------------
+
+// CodeGeneratorResponse
+
+// optional string error = 1;
+inline bool CodeGeneratorResponse::has_error() const {
+  return _has_bit(0);
+}
+inline void CodeGeneratorResponse::clear_error() {
+  if (error_ != &_default_error_) {
+    error_->clear();
+  }
+  _clear_bit(0);
+}
+inline const ::std::string& CodeGeneratorResponse::error() const {
+  return *error_;
+}
+inline void CodeGeneratorResponse::set_error(const ::std::string& value) {
+  _set_bit(0);
+  if (error_ == &_default_error_) {
+    error_ = new ::std::string;
+  }
+  error_->assign(value);
+}
+inline void CodeGeneratorResponse::set_error(const char* value) {
+  _set_bit(0);
+  if (error_ == &_default_error_) {
+    error_ = new ::std::string;
+  }
+  error_->assign(value);
+}
+inline void CodeGeneratorResponse::set_error(const char* value, size_t size) {
+  _set_bit(0);
+  if (error_ == &_default_error_) {
+    error_ = new ::std::string;
+  }
+  error_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* CodeGeneratorResponse::mutable_error() {
+  _set_bit(0);
+  if (error_ == &_default_error_) {
+    error_ = new ::std::string;
+  }
+  return error_;
+}
+
+// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
+inline int CodeGeneratorResponse::file_size() const {
+  return file_.size();
+}
+inline void CodeGeneratorResponse::clear_file() {
+  file_.Clear();
+}
+inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const {
+  return file_.Get(index);
+}
+inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) {
+  return file_.Mutable(index);
+}
+inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() {
+  return file_.Add();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >&
+CodeGeneratorResponse::file() const {
+  return file_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >*
+CodeGeneratorResponse::mutable_file() {
+  return &file_;
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+
+}  // namespace google
+}  // namespace protobuf
+#endif  // SWIG
+
+// @@protoc_insertion_point(global_scope)
+
+#endif  // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED

+ 130 - 0
src/google/protobuf/compiler/plugin.proto

@@ -0,0 +1,130 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// protoc (aka the Protocol Compiler) can be extended via plugins.  A plugin is
+// just a program that reads a CodeGeneratorRequest from stdin and writes a
+// CodeGeneratorResponse to stdout.
+//
+// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
+// of dealing with the raw protocol defined here.
+//
+// A plugin executable needs only to be placed somewhere in the path.  The
+// plugin should be named "protoc-gen-$NAME", and will then be used when the
+// flag "--${NAME}_out" is passed to protoc.
+
+package google.protobuf.compiler;
+
+import "google/protobuf/descriptor.proto";
+
+// An encoded CodeGeneratorRequest is written to the plugin's stdin.
+message CodeGeneratorRequest {
+  // The .proto files that were explicitly listed on the command-line.  The
+  // code generator should generate code only for these files.  Each file's
+  // descriptor will be included in proto_file, below.
+  repeated string file_to_generate = 1;
+
+  // The generator parameter passed on the command-line.
+  optional string parameter = 2;
+
+  // FileDescriptorProtos for all files in files_to_generate and everything
+  // they import.  The files will appear in topological order, so each file
+  // appears before any file that imports it.
+  //
+  // protoc guarantees that all proto_files will be written after
+  // the fields above, even though this is not technically guaranteed by the
+  // protobuf wire format.  This theoretically could allow a plugin to stream
+  // in the FileDescriptorProtos and handle them one by one rather than read
+  // the entire set into memory at once.  However, as of this writing, this
+  // is not similarly optimized on protoc's end -- it will store all fields in
+  // memory at once before sending them to the plugin.
+  repeated FileDescriptorProto proto_file = 15;
+}
+
+// The plugin writes an encoded CodeGeneratorResponse to stdout.
+message CodeGeneratorResponse {
+  // Error message.  If non-empty, code generation failed.  The plugin process
+  // should exit with status code zero even if it reports an error in this way.
+  //
+  // This should be used to indicate errors in .proto files which prevent the
+  // code generator from generating correct code.  Errors which indicate a
+  // problem in protoc itself -- such as the input CodeGeneratorRequest being
+  // unparseable -- should be reported by writing a message to stderr and
+  // exiting with a non-zero status code.
+  optional string error = 1;
+
+  // Represents a single generated file.
+  message File {
+    // The file name, relative to the output directory.  The name must not
+    // contain "." or ".." components and must be relative, not be absolute (so,
+    // the file cannot lie outside the output directory).  "/" must be used as
+    // the path separator, not "\".
+    //
+    // If the name is omitted, the content will be appended to the previous
+    // file.  This allows the generator to break large files into small chunks,
+    // and allows the generated text to be streamed back to protoc so that large
+    // files need not reside completely in memory at one time.  Note that as of
+    // this writing protoc does not optimize for this -- it will read the entire
+    // CodeGeneratorResponse before writing files to disk.
+    optional string name = 1;
+
+    // If non-empty, indicates that the named file should already exist, and the
+    // content here is to be inserted into that file at a defined insertion
+    // point.  This feature allows a code generator to extend the output
+    // produced by another code generator.  The original generator may provide
+    // insertion points by placing special annotations in the file that look
+    // like:
+    //   @@protoc_insertion_point(NAME)
+    // The annotation can have arbitrary text before and after it on the line,
+    // which allows it to be placed in a comment.  NAME should be replaced with
+    // an identifier naming the point -- this is what other generators will use
+    // as the insertion_point.  Code inserted at this point will be placed
+    // immediately above the line containing the insertion point (thus multiple
+    // insertions to the same point will come out in the order they were added).
+    // The double-@ is intended to make it unlikely that the generated code
+    // could contain things that look like insertion points by accident.
+    //
+    // For example, the C++ code generator places the following line in the
+    // .pb.h files that it generates:
+    //   // @@protoc_insertion_point(package_level_decls)
+    // This line appears within the scope of the file's package namespace, but
+    // outside of any particular class.  Another plugin can then specify the
+    // insertion_point "package_level_decls" to generate additional classes or
+    // other declarations that should be placed in this scope.
+    //
+    // If |insertion_point| is present, |name| must also be present.
+    optional string insertion_point = 2;
+
+    // The file contents.
+    optional string content = 15;
+  }
+  repeated File file = 15;
+}

+ 116 - 0
src/google/protobuf/compiler/python/python_plugin_unittest.cc

@@ -0,0 +1,116 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// TODO(kenton):  Share code with the versions of this test in other languages?
+//   It seemed like parameterizing it would add more complexity than it is
+//   worth.
+
+#include <google/protobuf/compiler/python/python_generator.h>
+#include <google/protobuf/compiler/command_line_interface.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace python {
+namespace {
+
+class TestGenerator : public CodeGenerator {
+ public:
+  TestGenerator() {}
+  ~TestGenerator() {}
+
+  virtual bool Generate(const FileDescriptor* file,
+                        const string& parameter,
+                        OutputDirectory* output_directory,
+                        string* error) const {
+    TryInsert("test_pb2.py", "imports", output_directory);
+    TryInsert("test_pb2.py", "module_scope", output_directory);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar", output_directory);
+    TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", output_directory);
+    return true;
+  }
+
+  void TryInsert(const string& filename, const string& insertion_point,
+                 OutputDirectory* output_directory) const {
+    scoped_ptr<io::ZeroCopyOutputStream> output(
+      output_directory->OpenForInsert(filename, insertion_point));
+    io::Printer printer(output.get(), '$');
+    printer.Print("// inserted $name$\n", "name", insertion_point);
+  }
+};
+
+// This test verifies that all the expected insertion points exist.  It does
+// not verify that they are correctly-placed; that would require actually
+// compiling the output which is a bit more than I care to do for this test.
+TEST(PythonPluginTest, PluginTest) {
+  File::WriteStringToFileOrDie(
+      "syntax = \"proto2\";\n"
+      "package foo;\n"
+      "message Bar {\n"
+      "  message Baz {}\n"
+      "}\n",
+      TestTempDir() + "/test.proto");
+
+  google::protobuf::compiler::CommandLineInterface cli;
+  cli.SetInputsAreProtoPathRelative(true);
+
+  python::Generator python_generator;
+  TestGenerator test_generator;
+  cli.RegisterGenerator("--python_out", &python_generator, "");
+  cli.RegisterGenerator("--test_out", &test_generator, "");
+
+  string proto_path = "-I" + TestTempDir();
+  string python_out = "--python_out=" + TestTempDir();
+  string test_out = "--test_out=" + TestTempDir();
+
+  const char* argv[] = {
+    "protoc",
+    proto_path.c_str(),
+    python_out.c_str(),
+    test_out.c_str(),
+    "test.proto"
+  };
+
+  EXPECT_EQ(0, cli.Run(5, argv));
+}
+
+}  // namespace
+}  // namespace python
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

+ 224 - 0
src/google/protobuf/compiler/subprocess.cc

@@ -0,0 +1,224 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#include <google/protobuf/compiler/subprocess.h>
+
+#include <algorithm>
+#include <errno.h>
+#include <sys/wait.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+Subprocess::Subprocess()
+    : child_pid_(-1), child_stdin_(-1), child_stdout_(-1) {}
+
+Subprocess::~Subprocess() {
+  if (child_stdin_ != -1) {
+    close(child_stdin_);
+  }
+  if (child_stdout_ != -1) {
+    close(child_stdout_);
+  }
+}
+
+void Subprocess::Start(const string& program, SearchMode search_mode) {
+  // Note that we assume that there are no other threads, thus we don't have to
+  // do crazy stuff like using socket pairs or avoiding libc locks.
+
+  // [0] is read end, [1] is write end.
+  int stdin_pipe[2];
+  int stdout_pipe[2];
+
+  pipe(stdin_pipe);
+  pipe(stdout_pipe);
+
+  char* argv[2] = { strdup(program.c_str()), NULL };
+
+  child_pid_ = fork();
+  if (child_pid_ == -1) {
+    GOOGLE_LOG(FATAL) << "fork: " << strerror(errno);
+  } else if (child_pid_ == 0) {
+    // We are the child.
+    dup2(stdin_pipe[0], STDIN_FILENO);
+    dup2(stdout_pipe[1], STDOUT_FILENO);
+
+    close(stdin_pipe[0]);
+    close(stdin_pipe[1]);
+    close(stdout_pipe[0]);
+    close(stdout_pipe[1]);
+
+    switch (search_mode) {
+      case SEARCH_PATH:
+        execvp(argv[0], argv);
+        break;
+      case EXACT_NAME:
+        execv(argv[0], argv);
+        break;
+    }
+
+    // Write directly to STDERR_FILENO to avoid stdio code paths that may do
+    // stuff that is unsafe here.
+    write(STDERR_FILENO, argv[0], strlen(argv[0]));
+    const char* message = ": program not found or is not executable\n";
+    write(STDERR_FILENO, message, strlen(message));
+
+    // Must use _exit() rather than exit() to avoid flushing output buffers
+    // that will also be flushed by the parent.
+    _exit(1);
+  } else {
+    free(argv[0]);
+
+    close(stdin_pipe[0]);
+    close(stdout_pipe[1]);
+
+    child_stdin_ = stdin_pipe[1];
+    child_stdout_ = stdout_pipe[0];
+  }
+}
+
+bool Subprocess::Communicate(const Message& input, Message* output,
+                             string* error) {
+
+  GOOGLE_CHECK_NE(child_stdin_, -1) << "Must call Start() first.";
+
+  // Make sure SIGPIPE is disabled so that if the child dies it doesn't kill us.
+  sighandler_t old_pipe_handler = signal(SIGPIPE, SIG_IGN);
+
+  string input_data = input.SerializeAsString();
+  string output_data;
+
+  int input_pos = 0;
+  int max_fd = max(child_stdin_, child_stdout_);
+
+  while (child_stdout_ != -1) {
+    fd_set read_fds;
+    fd_set write_fds;
+    FD_ZERO(&read_fds);
+    FD_ZERO(&write_fds);
+    if (child_stdout_ != -1) {
+      FD_SET(child_stdout_, &read_fds);
+    }
+    if (child_stdin_ != -1) {
+      FD_SET(child_stdin_, &write_fds);
+    }
+
+    if (select(max_fd + 1, &read_fds, &write_fds, NULL, NULL) < 0) {
+      if (errno == EINTR) {
+        // Interrupted by signal.  Try again.
+        continue;
+      } else {
+        GOOGLE_LOG(FATAL) << "select: " << strerror(errno);
+      }
+    }
+
+    if (child_stdin_ != -1 && FD_ISSET(child_stdin_, &write_fds)) {
+      int n = write(child_stdin_, input_data.data() + input_pos,
+                                  input_data.size() - input_pos);
+      if (n < 0) {
+        // Child closed pipe.  Presumably it will report an error later.
+        // Pretend we're done for now.
+        input_pos = input_data.size();
+      } else {
+        input_pos += n;
+      }
+
+      if (input_pos == input_data.size()) {
+        // We're done writing.  Close.
+        close(child_stdin_);
+        child_stdin_ = -1;
+      }
+    }
+
+    if (child_stdout_ != -1 && FD_ISSET(child_stdout_, &read_fds)) {
+      char buffer[4096];
+      int n = read(child_stdout_, buffer, sizeof(buffer));
+
+      if (n > 0) {
+        output_data.append(buffer, n);
+      } else {
+        // We're done reading.  Close.
+        close(child_stdout_);
+        child_stdout_ = -1;
+      }
+    }
+  }
+
+  if (child_stdin_ != -1) {
+    // Child did not finish reading input before it closed the output.
+    // Presumably it exited with an error.
+    close(child_stdin_);
+    child_stdin_ = -1;
+  }
+
+  int status;
+  while (waitpid(child_pid_, &status, 0) == -1) {
+    if (errno != EINTR) {
+      GOOGLE_LOG(FATAL) << "waitpid: " << strerror(errno);
+    }
+  }
+
+  // Restore SIGPIPE handling.
+  signal(SIGPIPE, old_pipe_handler);
+
+  if (WIFEXITED(status)) {
+    if (WEXITSTATUS(status) != 0) {
+      int error_code = WEXITSTATUS(status);
+      *error = strings::Substitute(
+          "Plugin failed with status code $0.", error_code);
+      return false;
+    }
+  } else if (WIFSIGNALED(status)) {
+    int signal = WTERMSIG(status);
+    *error = strings::Substitute(
+        "Plugin killed by signal $0.", signal);
+    return false;
+  } else {
+    *error = "Neither WEXITSTATUS nor WTERMSIG is true?";
+    return false;
+  }
+
+  if (!output->ParseFromString(output_data)) {
+    *error = "Plugin output is unparseable.";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google

+ 85 - 0
src/google/protobuf/compiler/subprocess.h

@@ -0,0 +1,85 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+#define GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
+
+#include <vector>
+#include <string>
+#include <sys/types.h>
+#include <unistd.h>
+#include <google/protobuf/stubs/common.h>
+
+
+namespace google {
+namespace protobuf {
+
+class Message;
+
+namespace compiler {
+
+// Utility class for launching sub-processes.
+class Subprocess {
+ public:
+  Subprocess();
+  ~Subprocess();
+
+  enum SearchMode {
+    SEARCH_PATH,   // Use PATH environment variable.
+    EXACT_NAME     // Program is an exact file name; don't use the PATH.
+  };
+
+  // Start the subprocess.  Currently we don't provide a way to specify
+  // arguments as protoc plugins don't have any.
+  void Start(const string& program, SearchMode search_mode);
+
+  // Serialize the input message and pipe it to the subprocess's stdin, then
+  // close the pipe.  Meanwhile, read from the subprocess's stdout and parse
+  // the data into *output.  All this is done carefully to avoid deadlocks.
+  // Returns true if successful.  On any sort of error, returns false and sets
+  // *error to a description of the problem.
+  bool Communicate(const Message& input, Message* output, string* error);
+
+ private:
+  pid_t child_pid_;
+
+  // The file descriptors for our end of the child's pipes.  We close each and
+  // set it to -1 when no longer needed.
+  int child_stdin_;
+  int child_stdout_;
+};
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__

+ 44 - 0
src/google/protobuf/compiler/test_plugin.cc

@@ -0,0 +1,44 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+//
+// This is a dummy code generator plugin used by
+// command_line_interface_unittest.
+
+#include <string>
+#include <google/protobuf/compiler/plugin.h>
+#include <google/protobuf/compiler/mock_code_generator.h>
+#include <google/protobuf/stubs/strutil.h>
+
+int main(int argc, char* argv[]) {
+  google::protobuf::compiler::MockCodeGenerator generator("test_plugin");
+  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
+}

+ 64 - 0
src/google/protobuf/io/coded_stream_inl.h

@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: jasonh@google.com (Jason Hsueh)
+//
+// Implements methods of coded_stream.h that need to be inlined for performance
+// reasons, but should not be defined in a public header.
+
+#ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
+#define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__
+
+#include <google/protobuf/io/coded_stream.h>
+#include <string>
+#include <google/protobuf/stubs/stl_util-inl.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+inline bool CodedInputStream::InternalReadStringInline(string* buffer,
+                                                       int size) {
+  if (size < 0) return false;  // security: size is often user-supplied
+
+  if (BufferSize() >= size) {
+    STLStringResizeUninitialized(buffer, size);
+    memcpy(string_as_array(buffer), buffer_, size);
+    Advance(size);
+    return true;
+  }
+
+  return ReadStringFallback(buffer, size);
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__

+ 54 - 0
src/google/protobuf/unittest_no_generic_services.proto

@@ -0,0 +1,54 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Author: kenton@google.com (Kenton Varda)
+
+package google.protobuf.no_generic_services_test;
+
+option cc_generic_services = false;
+option java_generic_services = false;
+option py_generic_services = false;
+
+message TestMessage {
+  optional int32 a = 1;
+  extensions 1000 to max;
+}
+
+enum TestEnum {
+  FOO = 1;
+}
+
+extend TestMessage {
+  optional int32 test_extension = 1000;
+}
+
+service TestService {
+  rpc Foo(TestMessage) returns(TestMessage);
+}