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; 905