1// Protocol Buffers - Google's data interchange format 2// Copyright 2008 Google Inc. All rights reserved. 3// http://code.google.com/p/protobuf/ 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/common.h> 52#include <google/protobuf/compiler/plugin.pb.h> 53#include <google/protobuf/compiler/code_generator.h> 54#include <google/protobuf/descriptor.h> 55#include <google/protobuf/io/zero_copy_stream_impl.h> 56 57 58namespace google { 59namespace protobuf { 60namespace compiler { 61 62class GeneratorResponseOutputDirectory : public OutputDirectory { 63 public: 64 GeneratorResponseOutputDirectory(CodeGeneratorResponse* response) 65 : response_(response) {} 66 virtual ~GeneratorResponseOutputDirectory() {} 67 68 // implements OutputDirectory -------------------------------------- 69 70 virtual io::ZeroCopyOutputStream* Open(const string& filename) { 71 CodeGeneratorResponse::File* file = response_->add_file(); 72 file->set_name(filename); 73 return new io::StringOutputStream(file->mutable_content()); 74 } 75 76 virtual io::ZeroCopyOutputStream* OpenForInsert( 77 const string& filename, const string& insertion_point) { 78 CodeGeneratorResponse::File* file = response_->add_file(); 79 file->set_name(filename); 80 file->set_insertion_point(insertion_point); 81 return new io::StringOutputStream(file->mutable_content()); 82 } 83 84 private: 85 CodeGeneratorResponse* response_; 86}; 87 88int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { 89 90 if (argc > 1) { 91 cerr << argv[0] << ": Unknown option: " << argv[1] << endl; 92 return 1; 93 } 94 95#ifdef _WIN32 96 _setmode(STDIN_FILENO, _O_BINARY); 97 _setmode(STDOUT_FILENO, _O_BINARY); 98#endif 99 100 CodeGeneratorRequest request; 101 if (!request.ParseFromFileDescriptor(STDIN_FILENO)) { 102 cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl; 103 return 1; 104 } 105 106 DescriptorPool pool; 107 for (int i = 0; i < request.proto_file_size(); i++) { 108 const FileDescriptor* file = pool.BuildFile(request.proto_file(i)); 109 if (file == NULL) { 110 // BuildFile() already wrote an error message. 111 return 1; 112 } 113 } 114 115 CodeGeneratorResponse response; 116 GeneratorResponseOutputDirectory output_directory(&response); 117 118 for (int i = 0; i < request.file_to_generate_size(); i++) { 119 const FileDescriptor* file = 120 pool.FindFileByName(request.file_to_generate(i)); 121 if (file == NULL) { 122 cerr << argv[0] << ": protoc asked plugin to generate a file but " 123 "did not provide a descriptor for the file: " 124 << request.file_to_generate(i) << endl; 125 return 1; 126 } 127 128 string error; 129 bool succeeded = generator->Generate( 130 file, request.parameter(), &output_directory, &error); 131 132 if (!succeeded && error.empty()) { 133 error = "Code generator returned false but provided no error " 134 "description."; 135 } 136 if (!error.empty()) { 137 response.set_error(file->name() + ": " + error); 138 break; 139 } 140 } 141 142 if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) { 143 cerr << argv[0] << ": Error writing to stdout." << endl; 144 return 1; 145 } 146 147 return 0; 148} 149 150} // namespace compiler 151} // namespace protobuf 152} // namespace google 153