1d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Protocol Buffers - Google's data interchange format
2d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Copyright 2008 Google Inc.  All rights reserved.
3d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// http://code.google.com/p/protobuf/
4d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
5d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Redistribution and use in source and binary forms, with or without
6d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// modification, are permitted provided that the following conditions are
7d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// met:
8d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
9d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Redistributions of source code must retain the above copyright
10d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// notice, this list of conditions and the following disclaimer.
11d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Redistributions in binary form must reproduce the above
12d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// copyright notice, this list of conditions and the following disclaimer
13d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// in the documentation and/or other materials provided with the
14d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// distribution.
15d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//     * Neither the name of Google Inc. nor the names of its
16d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// contributors may be used to endorse or promote products derived from
17d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// this software without specific prior written permission.
18d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville//
19d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
31d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Author: kenton@google.com (Kenton Varda)
32d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
33d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/plugin.h>
34d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
35d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <iostream>
36d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <set>
37d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
38d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifdef _WIN32
39d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <io.h>
40d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <fcntl.h>
41d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifndef STDIN_FILENO
42d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#define STDIN_FILENO 0
43d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
44d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifndef STDOUT_FILENO
45d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#define STDOUT_FILENO 1
46d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
47d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#else
48d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <unistd.h>
49d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
51d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/common.h>
52d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/plugin.pb.h>
53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/code_generator.h>
54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/descriptor.h>
55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/io/zero_copy_stream_impl.h>
56d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
57d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
58d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace google {
59d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace protobuf {
60d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillenamespace compiler {
61d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
62d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleclass GeneratorResponseOutputDirectory : public OutputDirectory {
63d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville public:
64d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  GeneratorResponseOutputDirectory(CodeGeneratorResponse* response)
65d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      : response_(response) {}
66d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  virtual ~GeneratorResponseOutputDirectory() {}
67d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
68d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  // implements OutputDirectory --------------------------------------
69d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
70d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  virtual io::ZeroCopyOutputStream* Open(const string& filename) {
71d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CodeGeneratorResponse::File* file = response_->add_file();
72d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    file->set_name(filename);
73d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return new io::StringOutputStream(file->mutable_content());
74d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
75d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
76d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  virtual io::ZeroCopyOutputStream* OpenForInsert(
77d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      const string& filename, const string& insertion_point) {
78d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    CodeGeneratorResponse::File* file = response_->add_file();
79d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    file->set_name(filename);
80d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    file->set_insertion_point(insertion_point);
81d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return new io::StringOutputStream(file->mutable_content());
82d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
83d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
84d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville private:
85d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CodeGeneratorResponse* response_;
86d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville};
87d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
88d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleint PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
89d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
90d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (argc > 1) {
91d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cerr << argv[0] << ": Unknown option: " << argv[1] << endl;
92d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return 1;
93d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
94d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
95d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#ifdef _WIN32
96d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  _setmode(STDIN_FILENO, _O_BINARY);
97d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  _setmode(STDOUT_FILENO, _O_BINARY);
98d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#endif
99d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CodeGeneratorRequest request;
101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!request.ParseFromFileDescriptor(STDIN_FILENO)) {
102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl;
103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return 1;
104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  DescriptorPool pool;
107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  for (int i = 0; i < request.proto_file_size(); i++) {
108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const FileDescriptor* file = pool.BuildFile(request.proto_file(i));
109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (file == NULL) {
110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      // BuildFile() already wrote an error message.
111d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return 1;
112d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  CodeGeneratorResponse response;
116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  GeneratorResponseOutputDirectory output_directory(&response);
117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  for (int i = 0; i < request.file_to_generate_size(); i++) {
119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    const FileDescriptor* file =
120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        pool.FindFileByName(request.file_to_generate(i));
121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (file == NULL) {
122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      cerr << argv[0] << ": protoc asked plugin to generate a file but "
123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville              "did not provide a descriptor for the file: "
124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville           << request.file_to_generate(i) << endl;
125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      return 1;
126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    string error;
129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    bool succeeded = generator->Generate(
130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville        file, request.parameter(), &output_directory, &error);
131d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
132d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (!succeeded && error.empty()) {
133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      error = "Code generator returned false but provided no error "
134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville              "description.";
135d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    if (!error.empty()) {
137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      response.set_error(file->name() + ": " + error);
138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville      break;
139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    cerr << argv[0] << ": Error writing to stdout." << endl;
144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return 1;
145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  return 0;
148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}
149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace compiler
151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace protobuf
152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville}  // namespace google
153