1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format 2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc. All rights reserved. 3fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// http://code.google.com/p/protobuf/ 4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without 6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are 7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met: 8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions of source code must retain the above copyright 10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer. 11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Redistributions in binary form must reproduce the above 12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer 13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the 14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution. 15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// * Neither the name of Google Inc. nor the names of its 16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from 17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission. 18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// 19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Author: kenton@google.com (Kenton Varda) 32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Based on original Protocol Buffers design by 33fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Sanjay Ghemawat, Jeff Dean, and others. 34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 35d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/command_line_interface.h> 36d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 37fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <stdio.h> 38fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/types.h> 39fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <sys/stat.h> 40fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <fcntl.h> 41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _MSC_VER 42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <io.h> 43fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <direct.h> 44fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 45fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <unistd.h> 46fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 47fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <errno.h> 48fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <iostream> 49fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <ctype.h> 50fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 51fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/importer.h> 52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/compiler/code_generator.h> 53d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/plugin.pb.h> 54d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/subprocess.h> 55d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/compiler/zip_writer.h> 56fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/descriptor.h> 57fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/text_format.h> 58fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/dynamic_message.h> 59fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/io/zero_copy_stream_impl.h> 60d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/io/printer.h> 61fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/common.h> 62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#include <google/protobuf/stubs/strutil.h> 63d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/substitute.h> 64d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/map-util.h> 65d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/stl_util-inl.h> 66d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville#include <google/protobuf/stubs/hash.h> 67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 68fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace google { 70fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace protobuf { 71fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace compiler { 72fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 73fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32) 74fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define mkdir(name, mode) mkdir(name) 75fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef W_OK 76fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define W_OK 02 // not defined by MSVC for whatever reason 77fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 78fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef F_OK 79fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define F_OK 00 // not defined by MSVC for whatever reason 80fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 81fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef STDIN_FILENO 82fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define STDIN_FILENO 0 83fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 84fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef STDOUT_FILENO 85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define STDOUT_FILENO 1 86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 87fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 88fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 89fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifndef O_BINARY 90fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _O_BINARY 91fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define O_BINARY _O_BINARY 92fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 93fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#define O_BINARY 0 // If this isn't defined, the platform doesn't need it. 94fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 95fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 96fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 97fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillenamespace { 98fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32) && !defined(__CYGWIN__) 99fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic const char* kPathSeparator = ";"; 100fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 101fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic const char* kPathSeparator = ":"; 102fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 103fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Returns true if the text looks like a Windows-style absolute path, starting 105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// with a drive letter. Example: "C:\foo". TODO(kenton): Share this with 106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copy in importer.cc? 107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillestatic bool IsWindowsAbsolutePath(const string& text) { 108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#if defined(_WIN32) || defined(__CYGWIN__) 109fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return text.size() >= 3 && text[1] == ':' && 110fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville isalpha(text[0]) && 111fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville (text[2] == '/' || text[2] == '\\') && 112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville text.find_last_of(':') == 1; 113fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#else 114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid SetFdToTextMode(int fd) { 119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (_setmode(fd, _O_TEXT) == -1) { 121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // This should never happen, I think. 122fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_TEXT): " << strerror(errno); 123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // (Text and binary are the same on non-Windows platforms.) 126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid SetFdToBinaryMode(int fd) { 129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#ifdef _WIN32 130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (_setmode(fd, _O_BINARY) == -1) { 131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // This should never happen, I think. 132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_BINARY): " << strerror(errno); 133fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville#endif 135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // (Text and binary are the same on non-Windows platforms.) 136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid AddTrailingSlash(string* path) { 139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!path->empty() && path->at(path->size() - 1) != '/') { 140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville path->push_back('/'); 141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool VerifyDirectoryExists(const string& path) { 145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (path.empty()) return true; 146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (access(path.c_str(), W_OK) == -1) { 148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << path << ": " << strerror(errno) << endl; 149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return true; 152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// Try to create the parent directory of the given file, creating the parent's 156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// parent if necessary, and so on. The full file name is actually 157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// (prefix + filename), but we assume |prefix| already exists and only create 158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// directories listed in |filename|. 159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool TryCreateParentDirectory(const string& prefix, const string& filename) { 160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Recursively create parent directories to the output file. 161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville vector<string> parts; 162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville SplitStringUsing(filename, "/", &parts); 163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string path_so_far = prefix; 164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < parts.size() - 1; i++) { 165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville path_so_far += parts[i]; 166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (mkdir(path_so_far.c_str(), 0777) != 0) { 167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (errno != EEXIST) { 168d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": while trying to create directory " 169d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << path_so_far << ": " << strerror(errno) << endl; 170d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 171d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville path_so_far += '/'; 174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 176d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return true; 177d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 178d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 179fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace 180fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 181fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A MultiFileErrorCollector that prints errors to stderr. 182fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleclass CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, 183fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public io::ErrorCollector { 184fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 185fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ErrorPrinter(ErrorFormat format) : format_(format) {} 186fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ~ErrorPrinter() {} 187fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 188fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // implements MultiFileErrorCollector ------------------------------ 189fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void AddError(const string& filename, int line, int column, 190fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const string& message) { 191fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 192fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << filename; 193fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 194fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Users typically expect 1-based line/column numbers, so we add 1 195fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // to each here. 196fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (line != -1) { 197fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Allow for both GCC- and Visual-Studio-compatible output. 198fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville switch (format_) { 199fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case CommandLineInterface::ERROR_FORMAT_GCC: 200fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << ":" << (line + 1) << ":" << (column + 1); 201fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 202fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case CommandLineInterface::ERROR_FORMAT_MSVS: 203fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "(" << (line + 1) << ") : error in column=" << (column + 1); 204fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 205fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 206fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 207fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << ": " << message << endl; 209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // implements io::ErrorCollector ----------------------------------- 212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville void AddError(int line, int column, const string& message) { 213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville AddError("input", line, column, message); 214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private: 217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const ErrorFormat format_; 218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ------------------------------------------------------------------- 221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 222d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// An OutputDirectory implementation that buffers files in memory, then dumps 223d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// them all to disk on demand. 224d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleclass CommandLineInterface::MemoryOutputDirectory : public OutputDirectory { 225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 226d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputDirectory(); 227d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ~MemoryOutputDirectory(); 228d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 229d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Write all files in the directory to disk at the given output location, 230d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // which must end in a '/'. 231d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville bool WriteAllToDisk(const string& prefix); 232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 233d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Write the contents of this directory to a ZIP-format archive with the 234d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // given name. 235d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville bool WriteAllToZip(const string& filename); 236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 237d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR 238d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // format, unless one has already been written. 239d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville void AddJarManifest(); 240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // implements OutputDirectory -------------------------------------- 242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::ZeroCopyOutputStream* Open(const string& filename); 243d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville io::ZeroCopyOutputStream* OpenForInsert( 244d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& filename, const string& insertion_point); 245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private: 247d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville friend class MemoryOutputStream; 248d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 249d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // map instead of hash_map so that files are written in order (good when 250d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // writing zips). 251d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville map<string, string*> files_; 252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool had_error_; 253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 255d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleclass CommandLineInterface::MemoryOutputStream 256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville : public io::ZeroCopyOutputStream { 257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville public: 258d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename); 259d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputStream(MemoryOutputDirectory* directory, const string& filename, 260d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& insertion_point); 261d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual ~MemoryOutputStream(); 262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // implements ZeroCopyOutputStream --------------------------------- 264d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual bool Next(void** data, int* size) { return inner_->Next(data, size); } 265d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual void BackUp(int count) { inner_->BackUp(count); } 266d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville virtual int64 ByteCount() const { return inner_->ByteCount(); } 267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville private: 269d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Where to insert the string when it's done. 270d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputDirectory* directory_; 271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string filename_; 272d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string insertion_point_; 273d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 274d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // The string we're building. 275d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string data_; 276d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 277d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // StringOutputStream writing to data_. 278d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville scoped_ptr<io::StringOutputStream> inner_; 279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}; 280fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 281fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// ------------------------------------------------------------------- 282fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleCommandLineInterface::MemoryOutputDirectory::MemoryOutputDirectory() 284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville : had_error_(false) {} 285fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleCommandLineInterface::MemoryOutputDirectory::~MemoryOutputDirectory() { 287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville STLDeleteValues(&files_); 288fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 289fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 290d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool CommandLineInterface::MemoryOutputDirectory::WriteAllToDisk( 291d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& prefix) { 292d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (had_error_) { 293d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 294d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 295d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 296d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!VerifyDirectoryExists(prefix)) { 297d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 298d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 299d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 300d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (map<string, string*>::const_iterator iter = files_.begin(); 301d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville iter != files_.end(); ++iter) { 302d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& relative_filename = iter->first; 303d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const char* data = iter->second->data(); 304d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int size = iter->second->size(); 305d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 306d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!TryCreateParentDirectory(prefix, relative_filename)) { 307d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 308d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 309d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string filename = prefix + relative_filename; 310d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 311d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Create the output file. 312d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int file_descriptor; 313d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville do { 314d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville file_descriptor = 315d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); 316d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } while (file_descriptor < 0 && errno == EINTR); 317d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 318d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (file_descriptor < 0) { 319d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int error = errno; 320d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": " << strerror(error); 321d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Write the file. 325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville while (size > 0) { 326d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int write_result; 327d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville do { 328d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville write_result = write(file_descriptor, data, size); 329d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } while (write_result < 0 && errno == EINTR); 330d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 331d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (write_result <= 0) { 332d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Write error. 333d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 334d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // FIXME(kenton): According to the man page, if write() returns zero, 335d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // there was no error; write() simply did not write anything. It's 336d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // unclear under what circumstances this might happen, but presumably 337d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // errno won't be set in this case. I am confused as to how such an 338d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // event should be handled. For now I'm treating it as an error, 339d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // since retrying seems like it could lead to an infinite loop. I 340d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // suspect this never actually happens anyway. 341d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 342d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (write_result < 0) { 343d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int error = errno; 344d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": write: " << strerror(error); 345d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 346d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": write() returned zero?" << endl; 347d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 348d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 349d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 350d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 351d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville data += write_result; 352d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville size -= write_result; 353d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (close(file_descriptor) != 0) { 356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int error = errno; 357d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": close: " << strerror(error); 358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 359fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 360fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 361fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 362fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 363fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 365d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool CommandLineInterface::MemoryOutputDirectory::WriteAllToZip( 366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const string& filename) { 367d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (had_error_) { 368d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 371fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Create the output file. 372fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int file_descriptor; 373fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville do { 374fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file_descriptor = 375d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); 376fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } while (file_descriptor < 0 && errno == EINTR); 377fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 378fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (file_descriptor < 0) { 379d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int error = errno; 380d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": " << strerror(error); 381d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 382fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 384d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Create the ZipWriter 385d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville io::FileOutputStream stream(file_descriptor); 386d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ZipWriter zip_writer(&stream); 387d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 388d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (map<string, string*>::const_iterator iter = files_.begin(); 389d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville iter != files_.end(); ++iter) { 390d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville zip_writer.Write(iter->first, *iter->second); 391d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 392d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 393d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville zip_writer.WriteDirectory(); 394d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 395d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (stream.GetErrno() != 0) { 396d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": " << strerror(stream.GetErrno()) << endl; 397d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 398fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 399d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!stream.Close()) { 400d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename << ": " << strerror(stream.GetErrno()) << endl; 401d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 402d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 403d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return true; 404d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 405fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 406d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid CommandLineInterface::MemoryOutputDirectory::AddJarManifest() { 407d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string** map_slot = &files_["META-INF/MANIFEST.MF"]; 408d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (*map_slot == NULL) { 409d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *map_slot = new string( 410d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "Manifest-Version: 1.0\n" 411d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "Created-By: 1.6.0 (protoc)\n" 412d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "\n"); 413fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 414d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 415d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 416d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleio::ZeroCopyOutputStream* CommandLineInterface::MemoryOutputDirectory::Open( 417d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& filename) { 418d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return new MemoryOutputStream(this, filename); 419d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 420d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 421d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleio::ZeroCopyOutputStream* 422d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleCommandLineInterface::MemoryOutputDirectory::OpenForInsert( 423d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& filename, const string& insertion_point) { 424d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return new MemoryOutputStream(this, filename, insertion_point); 425d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 426d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 427d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville// ------------------------------------------------------------------- 428d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 429d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleCommandLineInterface::MemoryOutputStream::MemoryOutputStream( 430d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputDirectory* directory, const string& filename) 431d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville : directory_(directory), 432d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville filename_(filename), 433d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville inner_(new io::StringOutputStream(&data_)) { 434d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 435d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 436d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleCommandLineInterface::MemoryOutputStream::MemoryOutputStream( 437d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputDirectory* directory, const string& filename, 438d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& insertion_point) 439d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville : directory_(directory), 440d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville filename_(filename), 441d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville insertion_point_(insertion_point), 442d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville inner_(new io::StringOutputStream(&data_)) { 443d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 444d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 445d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink SavilleCommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { 446d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Make sure all data has been written. 447d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville inner_.reset(); 448fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 449d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Insert into the directory. 450d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string** map_slot = &directory_->files_[filename_]; 451d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 452d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (insertion_point_.empty()) { 453d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // This was just a regular Open(). 454d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (*map_slot != NULL) { 455d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename_ << ": Tried to write the same file twice." << endl; 456d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville directory_->had_error_ = true; 457d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return; 458d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 459d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 460d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *map_slot = new string; 461d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville (*map_slot)->swap(data_); 462d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 463d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // This was an OpenForInsert(). 464d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 465d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // If the data doens't end with a clean line break, add one. 466d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!data_.empty() && data_[data_.size() - 1] != '\n') { 467d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville data_.push_back('\n'); 468d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 469d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 470d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Find the file we are going to insert into. 471d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (*map_slot == NULL) { 472d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename_ << ": Tried to insert into file that doesn't exist." 473d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << endl; 474d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville directory_->had_error_ = true; 475d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return; 476d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 477d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string* target = *map_slot; 478d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 479d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Find the insertion point. 480d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string magic_string = strings::Substitute( 481d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "@@protoc_insertion_point($0)", insertion_point_); 482d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string::size_type pos = target->find(magic_string); 483d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 484d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (pos == string::npos) { 485d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << filename_ << ": insertion point \"" << insertion_point_ 486d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << "\" not found." << endl; 487d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville directory_->had_error_ = true; 488d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return; 489d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 490d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 491d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Seek backwards to the beginning of the line, which is where we will 492d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // insert the data. Note that this has the effect of pushing the insertion 493d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // point down, so the data is inserted before it. This is intentional 494d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // because it means that multiple insertions at the same point will end 495d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // up in the expected order in the final output. 496d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville pos = target->find_last_of('\n', pos); 497d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (pos == string::npos) { 498d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Insertion point is on the first line. 499d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville pos = 0; 500d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 501d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Advance to character after '\n'. 502d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville ++pos; 503d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 504d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 505d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Extract indent. 506d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string indent_(*target, pos, target->find_first_not_of(" \t", pos) - pos); 507d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 508d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (indent_.empty()) { 509d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // No indent. This makes things easier. 510d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville target->insert(pos, data_); 511d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 512d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Calculate how much space we need. 513d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville int indent_size = 0; 514d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < data_.size(); i++) { 515d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (data_[i] == '\n') indent_size += indent_.size(); 516d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 517d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 518d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Make a hole for it. 519d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville target->insert(pos, data_.size() + indent_size, '\0'); 520d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 521d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Now copy in the data. 522d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string::size_type data_pos = 0; 523d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville char* target_ptr = string_as_array(target) + pos; 524d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville while (data_pos < data_.size()) { 525d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Copy indent. 526d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville memcpy(target_ptr, indent_.data(), indent_.size()); 527d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville target_ptr += indent_.size(); 528d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 529d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Copy line from data_. 530d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We already guaranteed that data_ ends with a newline (above), so this 531d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // search can't fail. 532d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string::size_type line_length = 533d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville data_.find_first_of('\n', data_pos) + 1 - data_pos; 534d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville memcpy(target_ptr, data_.data() + data_pos, line_length); 535d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville target_ptr += line_length; 536d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville data_pos += line_length; 537d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 538d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 539d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_CHECK_EQ(target_ptr, 540d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string_as_array(target) + pos + data_.size() + indent_size); 541d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 542fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 543fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 544fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 545fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// =================================================================== 546fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 547fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleCommandLineInterface::CommandLineInterface() 548fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville : mode_(MODE_COMPILE), 549fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville error_format_(ERROR_FORMAT_GCC), 550fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville imports_in_descriptor_set_(false), 551fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville disallow_services_(false), 552fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville inputs_are_proto_path_relative_(false) {} 553fbaaef999ba563838ebd00874ed8a1c01fbf286dWink SavilleCommandLineInterface::~CommandLineInterface() {} 554fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 555fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterface::RegisterGenerator(const string& flag_name, 556fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville CodeGenerator* generator, 557fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const string& help_text) { 558fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GeneratorInfo info; 559fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville info.generator = generator; 560fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville info.help_text = help_text; 561fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville generators_[flag_name] = info; 562fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 563fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 564d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { 565d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville plugin_prefix_ = exe_name_prefix; 566d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 567d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 568fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleint CommandLineInterface::Run(int argc, const char* const argv[]) { 569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Clear(); 570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!ParseArguments(argc, argv)) return 1; 571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Set up the source tree. 573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DiskSourceTree source_tree; 574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < proto_path_.size(); i++) { 575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville source_tree.MapPath(proto_path_[i].first, proto_path_[i].second); 576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 577fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Map input files to virtual paths if necessary. 579fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!inputs_are_proto_path_relative_) { 580fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!MakeInputsBeProtoPathRelative(&source_tree)) { 581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 1; 582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Allocate the Importer. 586fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ErrorPrinter error_collector(error_format_); 587fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville Importer importer(&source_tree, &error_collector); 588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 589fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vector<const FileDescriptor*> parsed_files; 590fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 591d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Parse each file. 592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < input_files_.size(); i++) { 593fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Import the file. 594fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const FileDescriptor* parsed_file = importer.Import(input_files_[i]); 595fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (parsed_file == NULL) return 1; 596fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville parsed_files.push_back(parsed_file); 597fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 598fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Enforce --disallow_services. 599fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (disallow_services_ && parsed_file->service_count() > 0) { 600fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << parsed_file->name() << ": This file contains services, but " 601fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "--disallow_services was used." << endl; 602fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 1; 603fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 604d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 605d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 606d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We construct a separate OutputDirectory for each output location. Note 607d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // that two code generators may output to the same location, in which case 608d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // they should share a single OutputDirectory (so that OpenForInsert() works). 609d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville typedef hash_map<string, MemoryOutputDirectory*> OutputDirectoryMap; 610d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville OutputDirectoryMap output_directories; 611d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 612d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Generate output. 613d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (mode_ == MODE_COMPILE) { 614d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < output_directives_.size(); i++) { 615d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string output_location = output_directives_[i].output_location; 616d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!HasSuffixString(output_location, ".zip") && 617d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville !HasSuffixString(output_location, ".jar")) { 618d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville AddTrailingSlash(&output_location); 619d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 620d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputDirectory** map_slot = &output_directories[output_location]; 621d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 622d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (*map_slot == NULL) { 623d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // First time we've seen this output location. 624d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *map_slot = new MemoryOutputDirectory; 625d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 626d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 627d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!GenerateOutput(parsed_files, output_directives_[i], *map_slot)) { 628d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville STLDeleteValues(&output_directories); 629d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return 1; 630d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 631d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 632d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 633fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 634d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Write all output to disk. 635d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (OutputDirectoryMap::iterator iter = output_directories.begin(); 636d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville iter != output_directories.end(); ++iter) { 637d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& location = iter->first; 638d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville MemoryOutputDirectory* directory = iter->second; 639d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (HasSuffixString(location, "/")) { 640d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!directory->WriteAllToDisk(location)) { 641d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville STLDeleteValues(&output_directories); 642d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return 1; 643d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 644d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 645d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (HasSuffixString(location, ".jar")) { 646d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville directory->AddJarManifest(); 647d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 648d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 649d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!directory->WriteAllToZip(location)) { 650d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville STLDeleteValues(&output_directories); 651d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return 1; 652fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 653fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 654fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 655fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 656d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville STLDeleteValues(&output_directories); 657d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 658fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!descriptor_set_name_.empty()) { 659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!WriteDescriptorSet(parsed_files)) { 660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 1; 661fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 662fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 663fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 664fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) { 665fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (codec_type_.empty()) { 666fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // HACK: Define an EmptyMessage type to use for decoding. 667fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DescriptorPool pool; 668fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FileDescriptorProto file; 669fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.set_name("empty_message.proto"); 670fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville file.add_message_type()->set_name("EmptyMessage"); 671fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville GOOGLE_CHECK(pool.BuildFile(file) != NULL); 672fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville codec_type_ = "EmptyMessage"; 673fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!EncodeOrDecode(&pool)) { 674fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 1; 675fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 676fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 677fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!EncodeOrDecode(importer.pool())) { 678fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 1; 679fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 680fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 681fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 682fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 683fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return 0; 684fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 685fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 686fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterface::Clear() { 687fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Clear all members that are set by Run(). Note that we must not clear 688fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // members which are set by other methods before Run() is called. 689fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville executable_name_.clear(); 690fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto_path_.clear(); 691fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville input_files_.clear(); 692fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville output_directives_.clear(); 693fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville codec_type_.clear(); 694fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor_set_name_.clear(); 695fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 696fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville mode_ = MODE_COMPILE; 697fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville imports_in_descriptor_set_ = false; 698fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville disallow_services_ = false; 699fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 700fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 701fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterface::MakeInputsBeProtoPathRelative( 702fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DiskSourceTree* source_tree) { 703fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < input_files_.size(); i++) { 704fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string virtual_file, shadowing_disk_file; 705fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville switch (source_tree->DiskFileToVirtualFile( 706fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville input_files_[i], &virtual_file, &shadowing_disk_file)) { 707fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case DiskSourceTree::SUCCESS: 708fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville input_files_[i] = virtual_file; 709fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville break; 710fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case DiskSourceTree::SHADOWED: 711fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << input_files_[i] << ": Input is shadowed in the --proto_path " 712fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "by \"" << shadowing_disk_file << "\". Either use the latter " 713fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "file as your input or reorder the --proto_path so that the " 714fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "former file's location comes first." << endl; 715fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 716fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case DiskSourceTree::CANNOT_OPEN: 717fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << input_files_[i] << ": " << strerror(errno) << endl; 718fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 719fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville case DiskSourceTree::NO_MAPPING: 720fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // First check if the file exists at all. 721fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (access(input_files_[i].c_str(), F_OK) < 0) { 722fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // File does not even exist. 723fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << input_files_[i] << ": " << strerror(ENOENT) << endl; 724fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 725fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << input_files_[i] << ": File does not reside within any path " 726fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "specified using --proto_path (or -I). You must specify a " 727d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "--proto_path which encompasses this file. Note that the " 728d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "proto_path must be an exact prefix of the .proto file " 729d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "names -- protoc is too dumb to figure out when two paths " 730d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "(e.g. absolute and relative) are equivalent (it's harder " 731d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "than you think)." << endl; 732fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 733fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 734fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 735fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 736fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 737fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 738fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 739fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 740fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { 741fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville executable_name_ = argv[0]; 742fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 743fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Iterate through all arguments and parse them. 744fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 1; i < argc; i++) { 745fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string name, value; 746fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 747fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (ParseArgument(argv[i], &name, &value)) { 748fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Returned true => Use the next argument as the flag value. 749fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (i + 1 == argc || argv[i+1][0] == '-') { 750fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Missing value for flag: " << name << endl; 751fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name == "--decode") { 752fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "To decode an unknown message, use --decode_raw." << endl; 753fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 754fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 755fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 756fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ++i; 757fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville value = argv[i]; 758fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 759fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 760fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 761fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!InterpretArgument(name, value)) return false; 762fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 763fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 764fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // If no --proto_path was given, use the current working directory. 765fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (proto_path_.empty()) { 766fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto_path_.push_back(make_pair("", ".")); 767fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 768fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 769fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Check some errror cases. 770fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); 771fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (decoding_raw && !input_files_.empty()) { 772fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "When using --decode_raw, no input files should be given." << endl; 773fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 774fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (!decoding_raw && input_files_.empty()) { 775fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Missing input file." << endl; 776fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 777fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 778fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ == MODE_COMPILE && output_directives_.empty() && 779fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor_set_name_.empty()) { 780fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Missing output directives." << endl; 781fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 782fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 783fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { 784fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "--include_imports only makes sense when combined with " 785fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "--descriptor_set_out." << endl; 786fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 787fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 788fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 789fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 790fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 791fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterface::ParseArgument(const char* arg, 792fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string* name, string* value) { 793fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville bool parsed_value = false; 794fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 795fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (arg[0] != '-') { 796fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Not a flag. 797fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name->clear(); 798fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville parsed_value = true; 799fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *value = arg; 800fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (arg[1] == '-') { 801fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Two dashes: Multi-character name, with '=' separating name and 802fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // value. 803fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const char* equals_pos = strchr(arg, '='); 804fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (equals_pos != NULL) { 805fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *name = string(arg, equals_pos - arg); 806fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *value = equals_pos + 1; 807fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville parsed_value = true; 808fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 809fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *name = arg; 810fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 811fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 812fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // One dash: One-character name, all subsequent characters are the 813fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // value. 814fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (arg[1] == '\0') { 815fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // arg is just "-". We treat this as an input file, except that at 816fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // present this will just lead to a "file not found" error. 817fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name->clear(); 818fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *value = arg; 819fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville parsed_value = true; 820fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 821fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *name = string(arg, 2); 822fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *value = arg + 2; 823fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville parsed_value = !value->empty(); 824fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 825fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 826fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 827fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Need to return true iff the next arg should be used as the value for this 828fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // one, false otherwise. 829fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 830fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (parsed_value) { 831fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // We already parsed a value for this flag. 832fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 833fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 834fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 835fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (*name == "-h" || *name == "--help" || 836fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *name == "--disallow_services" || 837fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *name == "--include_imports" || 838fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *name == "--version" || 839fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *name == "--decode_raw") { 840fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // HACK: These are the only flags that don't take a value. 841fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // They probably should not be hard-coded like this but for now it's 842fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // not worth doing better. 843fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 844fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 845fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 846fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Next argument is the flag value. 847fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 848fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 849fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 850fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterface::InterpretArgument(const string& name, 851fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const string& value) { 852fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name.empty()) { 853fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Not a flag. Just a filename. 854fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (value.empty()) { 855fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "You seem to have passed an empty string as one of the " 856fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "arguments to " << executable_name_ << ". This is actually " 857fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "sort of hard to do. Congrats. Unfortunately it is not valid " 858fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "input so the program is going to die now." << endl; 859fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 860fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 861fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 862fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville input_files_.push_back(value); 863fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 864fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "-I" || name == "--proto_path") { 865fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Java's -classpath (and some other languages) delimits path components 866fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // with colons. Let's accept that syntax too just to make things more 867fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // intuitive. 868fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville vector<string> parts; 869fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SplitStringUsing(value, kPathSeparator, &parts); 870fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 871fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (int i = 0; i < parts.size(); i++) { 872fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string virtual_path; 873fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string disk_path; 874fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 875fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int equals_pos = parts[i].find_first_of('='); 876fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (equals_pos == string::npos) { 877fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville virtual_path = ""; 878fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville disk_path = parts[i]; 879fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 880fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville virtual_path = parts[i].substr(0, equals_pos); 881fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville disk_path = parts[i].substr(equals_pos + 1); 882fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 883fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 884fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (disk_path.empty()) { 885fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "--proto_path passed empty directory name. (Use \".\" for " 886fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "current directory.)" << endl; 887fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 888fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 889fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 890fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Make sure disk path exists, warn otherwise. 891fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (access(disk_path.c_str(), F_OK) < 0) { 892fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << disk_path << ": warning: directory does not exist." << endl; 893fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 894fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 895fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville proto_path_.push_back(make_pair(virtual_path, disk_path)); 896fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 897fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 898fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "-o" || name == "--descriptor_set_out") { 899fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!descriptor_set_name_.empty()) { 900fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << name << " may only be passed once." << endl; 901fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 902fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 903fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (value.empty()) { 904fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << name << " requires a non-empty value." << endl; 905fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 906fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 907fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ != MODE_COMPILE) { 908fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Cannot use --encode or --decode and generate descriptors at the " 909fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "same time." << endl; 910fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 911fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 912fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville descriptor_set_name_ = value; 913fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 914fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "--include_imports") { 915fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (imports_in_descriptor_set_) { 916fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << name << " may only be passed once." << endl; 917fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 918fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 919fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville imports_in_descriptor_set_ = true; 920fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 921fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "-h" || name == "--help") { 922fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville PrintHelpText(); 923fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; // Exit without running compiler. 924fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 925fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "--version") { 926fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!version_info_.empty()) { 927fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cout << version_info_ << endl; 928fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 929fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cout << "libprotoc " 930fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) 931fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << endl; 932fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; // Exit without running compiler. 933fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 934fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "--disallow_services") { 935fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville disallow_services_ = true; 936fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 937fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "--encode" || name == "--decode" || 938fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville name == "--decode_raw") { 939fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ != MODE_COMPILE) { 940fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Only one of --encode and --decode can be specified." << endl; 941fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 942fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 943fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!output_directives_.empty() || !descriptor_set_name_.empty()) { 944fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Cannot use " << name 945fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << " and generate code or descriptors at the same time." << endl; 946fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 947fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 948fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 949fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE; 950fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 951fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (value.empty() && name != "--decode_raw") { 952fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Type name for " << name << " cannot be blank." << endl; 953fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (name == "--decode") { 954fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "To decode an unknown message, use --decode_raw." << endl; 955fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 956fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 957fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (!value.empty() && name == "--decode_raw") { 958fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "--decode_raw does not take a parameter." << endl; 959fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 960fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 961fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 962fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville codec_type_ = value; 963fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 964fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (name == "--error_format") { 965fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (value == "gcc") { 966fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville error_format_ = ERROR_FORMAT_GCC; 967fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else if (value == "msvs") { 968fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville error_format_ = ERROR_FORMAT_MSVS; 969fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 970fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Unknown error format: " << value << endl; 971fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 972fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 973fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 974d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (name == "--plugin") { 975d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (plugin_prefix_.empty()) { 976d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << "This compiler does not support plugins." << endl; 977d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 978d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 979d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 980d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string name; 981d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string path; 982d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 983d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string::size_type equals_pos = value.find_first_of('='); 984d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (equals_pos == string::npos) { 985d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Use the basename of the file. 986d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string::size_type slash_pos = value.find_last_of('/'); 987d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (slash_pos == string::npos) { 988d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville name = value; 989d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 990d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville name = value.substr(slash_pos + 1); 991d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 992d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville path = value; 993d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 994d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville name = value.substr(0, equals_pos); 995d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville path = value.substr(equals_pos + 1); 996d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 997d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 998d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville plugins_[name] = path; 999d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1000fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1001fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Some other flag. Look it up in the generators list. 1002d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const GeneratorInfo* generator_info = FindOrNull(generators_, name); 1003d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (generator_info == NULL && 1004d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { 1005fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Unknown flag: " << name << endl; 1006fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1007fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1008fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1009fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // It's an output flag. Add it to the output directives. 1010fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ != MODE_COMPILE) { 1011fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Cannot use --encode or --decode and generate code at the " 1012fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville "same time." << endl; 1013fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1014fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1015fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1016fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville OutputDirective directive; 1017fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville directive.name = name; 1018d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (generator_info == NULL) { 1019d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville directive.generator = NULL; 1020d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 1021d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville directive.generator = generator_info->generator; 1022d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1023fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1024fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Split value at ':' to separate the generator parameter from the 1025fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // filename. However, avoid doing this if the colon is part of a valid 1026fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Windows-style absolute path. 1027fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville string::size_type colon_pos = value.find_first_of(':'); 1028fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { 1029fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville directive.output_location = value; 1030fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1031fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville directive.parameter = value.substr(0, colon_pos); 1032fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville directive.output_location = value.substr(colon_pos + 1); 1033fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1034fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1035fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville output_directives_.push_back(directive); 1036fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1037fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1038fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 1039fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 1040fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1041fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillevoid CommandLineInterface::PrintHelpText() { 1042fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Sorry for indentation here; line wrapping would be uglier. 1043fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << 1044fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n" 1045fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville"Parse PROTO_FILES and generate output based on the options given:\n" 1046fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" -IPATH, --proto_path=PATH Specify the directory in which to search for\n" 1047fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" imports. May be specified multiple times;\n" 1048fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" directories will be searched in order. If not\n" 1049fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" given, the current working directory is used.\n" 1050fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" --version Show version info and exit.\n" 1051fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" -h, --help Show this text and exit.\n" 1052fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" --encode=MESSAGE_TYPE Read a text-format message of the given type\n" 1053fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" from standard input and write it in binary\n" 1054fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" to standard output. The message type must\n" 1055fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" be defined in PROTO_FILES or their imports.\n" 1056fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" --decode=MESSAGE_TYPE Read a binary message of the given type from\n" 1057fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" standard input and write it in text format\n" 1058fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" to standard output. The message type must\n" 1059fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" be defined in PROTO_FILES or their imports.\n" 1060fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" --decode_raw Read an arbitrary protocol message from\n" 1061fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" standard input and write the raw tag/value\n" 1062fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" pairs in text format to standard output. No\n" 1063fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" PROTO_FILES should be given when using this\n" 1064fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" flag.\n" 1065fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" -oFILE, Writes a FileDescriptorSet (a protocol buffer,\n" 1066fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" --descriptor_set_out=FILE defined in descriptor.proto) containing all of\n" 1067fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" the input files to FILE.\n" 1068fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" --include_imports When using --descriptor_set_out, also include\n" 1069fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" all dependencies of the input files in the\n" 1070fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" set, so that the set is self-contained.\n" 1071fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" --error_format=FORMAT Set the format in which to print errors.\n" 1072fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" FORMAT may be 'gcc' (the default) or 'msvs'\n" 1073fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville" (Microsoft Visual Studio format)." << endl; 1074d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!plugin_prefix_.empty()) { 1075d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << 1076d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" --plugin=EXECUTABLE Specifies a plugin executable to use.\n" 1077d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" Normally, protoc searches the PATH for\n" 1078d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" plugins, but you may specify additional\n" 1079d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" executables not in the path using this flag.\n" 1080d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" Additionally, EXECUTABLE may be of the form\n" 1081d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" NAME=PATH, in which case the given plugin name\n" 1082d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" is mapped to the given executable even if\n" 1083d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville" the executable's own name differs." << endl; 1084d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1085fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1086fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville for (GeneratorMap::iterator iter = generators_.begin(); 1087fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville iter != generators_.end(); ++iter) { 1088fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // FIXME(kenton): If the text is long enough it will wrap, which is ugly, 1089fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // but fixing this nicely (e.g. splitting on spaces) is probably more 1090fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // trouble than it's worth. 1091fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << " " << iter->first << "=OUT_DIR " 1092fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << string(19 - iter->first.size(), ' ') // Spaces for alignment. 1093fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << iter->second.help_text << endl; 1094fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1095fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 1096fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1097fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterface::GenerateOutput( 1098d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const vector<const FileDescriptor*>& parsed_files, 1099d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const OutputDirective& output_directive, 1100d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville OutputDirectory* output_directory) { 1101d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Call the generator. 1102d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string error; 1103d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (output_directive.generator == NULL) { 1104d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // This is a plugin. 1105d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") && 1106d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville HasSuffixString(output_directive.name, "_out")) 1107d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << "Bad name for plugin generator: " << output_directive.name; 1108d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1109d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Strip the "--" and "_out" and add the plugin prefix. 1110d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string plugin_name = plugin_prefix_ + "gen-" + 1111d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville output_directive.name.substr(2, output_directive.name.size() - 6); 1112d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1113d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!GeneratePluginOutput(parsed_files, plugin_name, 1114d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville output_directive.parameter, 1115d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville output_directory, &error)) { 1116d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << output_directive.name << ": " << error << endl; 1117d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 1118d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1119d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 1120d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Regular generator. 1121d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < parsed_files.size(); i++) { 1122d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!output_directive.generator->Generate( 1123d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville parsed_files[i], output_directive.parameter, 1124d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville output_directory, &error)) { 1125d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Generator returned an error. 1126d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " 1127d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville << error << endl; 1128d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 1129d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1130d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1133d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return true; 1134d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 1135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1136d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillebool CommandLineInterface::GeneratePluginOutput( 1137d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const vector<const FileDescriptor*>& parsed_files, 1138d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& plugin_name, 1139d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const string& parameter, 1140d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville OutputDirectory* output_directory, 1141d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string* error) { 1142d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CodeGeneratorRequest request; 1143d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville CodeGeneratorResponse response; 1144d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1145d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Build the request. 1146d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!parameter.empty()) { 1147d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville request.set_parameter(parameter); 1148d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1149d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1150d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville set<const FileDescriptor*> already_seen; 1151d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < parsed_files.size(); i++) { 1152d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville request.add_file_to_generate(parsed_files[i]->name()); 1153d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GetTransitiveDependencies(parsed_files[i], &already_seen, 1154d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville request.mutable_proto_file()); 1155d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1156d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1157d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Invoke the plugin. 1158d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville Subprocess subprocess; 1159d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1160d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (plugins_.count(plugin_name) > 0) { 1161d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME); 1162d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 1163d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville subprocess.Start(plugin_name, Subprocess::SEARCH_PATH); 1164d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1165d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1166d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville string communicate_error; 1167d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!subprocess.Communicate(request, &response, &communicate_error)) { 1168d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = strings::Substitute("$0: $1", plugin_name, communicate_error); 1169fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1170fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1171fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1172d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Write the files. We do this even if there was a generator error in order 1173d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // to match the behavior of a compiled-in generator. 1174d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville scoped_ptr<io::ZeroCopyOutputStream> current_output; 1175d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < response.file_size(); i++) { 1176d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const CodeGeneratorResponse::File& output_file = response.file(i); 1177d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1178d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!output_file.insertion_point().empty()) { 1179d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Open a file for insert. 1180d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We reset current_output to NULL first so that the old file is closed 1181d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // before the new one is opened. 1182d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville current_output.reset(); 1183d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville current_output.reset(output_directory->OpenForInsert( 1184d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville output_file.name(), output_file.insertion_point())); 1185d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (!output_file.name().empty()) { 1186d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Starting a new file. Open it. 1187d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // We reset current_output to NULL first so that the old file is closed 1188d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // before the new one is opened. 1189d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville current_output.reset(); 1190d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville current_output.reset(output_directory->Open(output_file.name())); 1191d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else if (current_output == NULL) { 1192d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = strings::Substitute( 1193d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville "$0: First file chunk returned by plugin did not specify a file name.", 1194d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville plugin_name); 1195d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return false; 1196d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1197d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1198d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Use CodedOutputStream for convenience; otherwise we'd need to provide 1199d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // our own buffer-copying loop. 1200d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville io::CodedOutputStream writer(current_output.get()); 1201d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville writer.WriteString(output_file.content()); 1202d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1203d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1204d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Check for errors. 1205d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!response.error().empty()) { 1206d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Generator returned an error. 1207d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville *error = response.error(); 1208fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1209fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1210fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1211fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 1212fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 1213fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { 1215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Look up the type. 1216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const Descriptor* type = pool->FindMessageTypeByName(codec_type_); 1217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (type == NULL) { 1218fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Type not defined: " << codec_type_ << endl; 1219fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1221fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville DynamicMessageFactory dynamic_factory(pool); 1223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville scoped_ptr<Message> message(dynamic_factory.GetPrototype(type)->New()); 1224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1225fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ == MODE_ENCODE) { 1226fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetFdToTextMode(STDIN_FILENO); 1227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetFdToBinaryMode(STDOUT_FILENO); 1228fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1229fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetFdToBinaryMode(STDIN_FILENO); 1230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville SetFdToTextMode(STDOUT_FILENO); 1231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1233fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::FileInputStream in(STDIN_FILENO); 1234fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::FileOutputStream out(STDOUT_FILENO); 1235fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1236fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ == MODE_ENCODE) { 1237fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Input is text. 1238fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville ErrorPrinter error_collector(error_format_); 1239fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville TextFormat::Parser parser; 1240fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville parser.RecordErrorsTo(&error_collector); 1241fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville parser.AllowPartialMessage(true); 1242fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1243fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!parser.Parse(&in, message.get())) { 1244fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Failed to parse input." << endl; 1245fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1246fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1247fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1248fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Input is binary. 1249fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!message->ParsePartialFromZeroCopyStream(&in)) { 1250fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "Failed to parse input." << endl; 1251fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1252fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1253fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1254fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1255fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!message->IsInitialized()) { 1256fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "warning: Input message is missing required fields: " 1257fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville << message->InitializationErrorString() << endl; 1258fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (mode_ == MODE_ENCODE) { 1261fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Output is binary. 1262fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!message->SerializePartialToZeroCopyStream(&out)) { 1263fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "output: I/O error." << endl; 1264fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1265fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1266fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } else { 1267fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville // Output is text. 1268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!TextFormat::Print(*message, &out)) { 1269fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << "output: I/O error." << endl; 1270fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1271fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1272fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1273fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1274fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 1275fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 1276fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1277fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillebool CommandLineInterface::WriteDescriptorSet( 1278fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville const vector<const FileDescriptor*> parsed_files) { 1279fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville FileDescriptorSet file_set; 1280d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1281d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (imports_in_descriptor_set_) { 1282d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville set<const FileDescriptor*> already_seen; 1283d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < parsed_files.size(); i++) { 1284d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GetTransitiveDependencies( 1285d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville parsed_files[i], &already_seen, file_set.mutable_file()); 1286d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1287d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } else { 1288d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < parsed_files.size(); i++) { 1289d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville parsed_files[i]->CopyTo(file_set.add_file()); 1290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1293fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville int fd; 1294fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville do { 1295fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville fd = open(descriptor_set_name_.c_str(), 1296fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); 1297fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } while (fd < 0 && errno == EINTR); 1298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1299fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (fd < 0) { 1300fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville perror(descriptor_set_name_.c_str()); 1301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville io::FileOutputStream out(fd); 1305fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!file_set.SerializeToZeroCopyStream(&out)) { 1306fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; 1307fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville out.Close(); 1308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1309fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville if (!out.Close()) { 1311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; 1312fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return false; 1313fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville } 1314fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1315fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville return true; 1316fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} 1317fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1318d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savillevoid CommandLineInterface::GetTransitiveDependencies( 1319d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville const FileDescriptor* file, 1320d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville set<const FileDescriptor*>* already_seen, 1321d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville RepeatedPtrField<FileDescriptorProto>* output) { 1322d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville if (!already_seen->insert(file).second) { 1323d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Already saw this file. Skip. 1324d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville return; 1325d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1326d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1327d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Add all dependencies. 1328d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville for (int i = 0; i < file->dependency_count(); i++) { 1329d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville GetTransitiveDependencies(file->dependency(i), already_seen, output); 1330d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville } 1331d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1332d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville // Add this file. 1333d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville file->CopyTo(output->Add()); 1334d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville} 1335d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville 1336fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville 1337fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace compiler 1338fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace protobuf 1339fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville} // namespace google 1340