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