Index: third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc |
=================================================================== |
--- third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc (revision 216642) |
+++ third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc (working copy) |
@@ -59,12 +59,13 @@ |
#include <google/protobuf/descriptor.h> |
#include <google/protobuf/text_format.h> |
#include <google/protobuf/dynamic_message.h> |
+#include <google/protobuf/io/coded_stream.h> |
#include <google/protobuf/io/zero_copy_stream_impl.h> |
#include <google/protobuf/io/printer.h> |
#include <google/protobuf/stubs/strutil.h> |
#include <google/protobuf/stubs/substitute.h> |
#include <google/protobuf/stubs/map-util.h> |
-#include <google/protobuf/stubs/stl_util-inl.h> |
+#include <google/protobuf/stubs/stl_util.h> |
namespace google { |
@@ -145,7 +146,7 @@ |
bool VerifyDirectoryExists(const string& path) { |
if (path.empty()) return true; |
- if (access(path.c_str(), W_OK) == -1) { |
+ if (access(path.c_str(), F_OK) == -1) { |
cerr << path << ": " << strerror(errno) << endl; |
return false; |
} else { |
@@ -566,6 +567,7 @@ |
: mode_(MODE_COMPILE), |
error_format_(ERROR_FORMAT_GCC), |
imports_in_descriptor_set_(false), |
+ source_info_in_descriptor_set_(false), |
disallow_services_(false), |
inputs_are_proto_path_relative_(false) {} |
CommandLineInterface::~CommandLineInterface() {} |
@@ -574,18 +576,39 @@ |
CodeGenerator* generator, |
const string& help_text) { |
GeneratorInfo info; |
+ info.flag_name = flag_name; |
info.generator = generator; |
info.help_text = help_text; |
- generators_[flag_name] = info; |
+ generators_by_flag_name_[flag_name] = info; |
} |
+void CommandLineInterface::RegisterGenerator(const string& flag_name, |
+ const string& option_flag_name, |
+ CodeGenerator* generator, |
+ const string& help_text) { |
+ GeneratorInfo info; |
+ info.flag_name = flag_name; |
+ info.option_flag_name = option_flag_name; |
+ info.generator = generator; |
+ info.help_text = help_text; |
+ generators_by_flag_name_[flag_name] = info; |
+ generators_by_option_name_[option_flag_name] = info; |
+} |
+ |
void CommandLineInterface::AllowPlugins(const string& exe_name_prefix) { |
plugin_prefix_ = exe_name_prefix; |
} |
int CommandLineInterface::Run(int argc, const char* const argv[]) { |
Clear(); |
- if (!ParseArguments(argc, argv)) return 1; |
+ switch (ParseArguments(argc, argv)) { |
+ case PARSE_ARGUMENT_DONE_AND_EXIT: |
+ return 0; |
+ case PARSE_ARGUMENT_FAIL: |
+ return 1; |
+ case PARSE_ARGUMENT_DONE_AND_CONTINUE: |
+ break; |
+ } |
// Set up the source tree. |
DiskSourceTree source_tree; |
@@ -713,6 +736,7 @@ |
mode_ = MODE_COMPILE; |
imports_in_descriptor_set_ = false; |
+ source_info_in_descriptor_set_ = false; |
disallow_services_ = false; |
} |
@@ -755,7 +779,8 @@ |
return true; |
} |
-bool CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { |
+CommandLineInterface::ParseArgumentStatus |
+CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { |
executable_name_ = argv[0]; |
// Iterate through all arguments and parse them. |
@@ -769,41 +794,50 @@ |
if (name == "--decode") { |
cerr << "To decode an unknown message, use --decode_raw." << endl; |
} |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} else { |
++i; |
value = argv[i]; |
} |
} |
- if (!InterpretArgument(name, value)) return false; |
+ ParseArgumentStatus status = InterpretArgument(name, value); |
+ if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) |
+ return status; |
} |
// If no --proto_path was given, use the current working directory. |
if (proto_path_.empty()) { |
- proto_path_.push_back(make_pair<string, string>("", ".")); |
+ // Don't use make_pair as the old/default standard library on Solaris |
+ // doesn't support it without explicit template parameters, which are |
+ // incompatible with C++0x's make_pair. |
+ proto_path_.push_back(pair<string, string>("", ".")); |
} |
// Check some errror cases. |
bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); |
if (decoding_raw && !input_files_.empty()) { |
cerr << "When using --decode_raw, no input files should be given." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} else if (!decoding_raw && input_files_.empty()) { |
cerr << "Missing input file." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
if (mode_ == MODE_COMPILE && output_directives_.empty() && |
descriptor_set_name_.empty()) { |
cerr << "Missing output directives." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { |
cerr << "--include_imports only makes sense when combined with " |
"--descriptor_set_out." << endl; |
} |
+ if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) { |
+ cerr << "--include_source_info only makes sense when combined with " |
+ "--descriptor_set_out." << endl; |
+ } |
- return true; |
+ return PARSE_ARGUMENT_DONE_AND_CONTINUE; |
} |
bool CommandLineInterface::ParseArgument(const char* arg, |
@@ -853,6 +887,7 @@ |
if (*name == "-h" || *name == "--help" || |
*name == "--disallow_services" || |
*name == "--include_imports" || |
+ *name == "--include_source_info" || |
*name == "--version" || |
*name == "--decode_raw") { |
// HACK: These are the only flags that don't take a value. |
@@ -865,8 +900,9 @@ |
return true; |
} |
-bool CommandLineInterface::InterpretArgument(const string& name, |
- const string& value) { |
+CommandLineInterface::ParseArgumentStatus |
+CommandLineInterface::InterpretArgument(const string& name, |
+ const string& value) { |
if (name.empty()) { |
// Not a flag. Just a filename. |
if (value.empty()) { |
@@ -874,7 +910,7 @@ |
"arguments to " << executable_name_ << ". This is actually " |
"sort of hard to do. Congrats. Unfortunately it is not valid " |
"input so the program is going to die now." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
input_files_.push_back(value); |
@@ -902,7 +938,7 @@ |
if (disk_path.empty()) { |
cerr << "--proto_path passed empty directory name. (Use \".\" for " |
"current directory.)" << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
// Make sure disk path exists, warn otherwise. |
@@ -910,35 +946,45 @@ |
cerr << disk_path << ": warning: directory does not exist." << endl; |
} |
- proto_path_.push_back(make_pair(virtual_path, disk_path)); |
+ // Don't use make_pair as the old/default standard library on Solaris |
+ // doesn't support it without explicit template parameters, which are |
+ // incompatible with C++0x's make_pair. |
+ proto_path_.push_back(pair<string, string>(virtual_path, disk_path)); |
} |
} else if (name == "-o" || name == "--descriptor_set_out") { |
if (!descriptor_set_name_.empty()) { |
cerr << name << " may only be passed once." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
if (value.empty()) { |
cerr << name << " requires a non-empty value." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
if (mode_ != MODE_COMPILE) { |
cerr << "Cannot use --encode or --decode and generate descriptors at the " |
"same time." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
descriptor_set_name_ = value; |
} else if (name == "--include_imports") { |
if (imports_in_descriptor_set_) { |
cerr << name << " may only be passed once." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
imports_in_descriptor_set_ = true; |
+ } else if (name == "--include_source_info") { |
+ if (source_info_in_descriptor_set_) { |
+ cerr << name << " may only be passed once." << endl; |
+ return PARSE_ARGUMENT_FAIL; |
+ } |
+ source_info_in_descriptor_set_ = true; |
+ |
} else if (name == "-h" || name == "--help") { |
PrintHelpText(); |
- return false; // Exit without running compiler. |
+ return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. |
} else if (name == "--version") { |
if (!version_info_.empty()) { |
@@ -947,7 +993,7 @@ |
cout << "libprotoc " |
<< protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) |
<< endl; |
- return false; // Exit without running compiler. |
+ return PARSE_ARGUMENT_DONE_AND_EXIT; // Exit without running compiler. |
} else if (name == "--disallow_services") { |
disallow_services_ = true; |
@@ -956,12 +1002,12 @@ |
name == "--decode_raw") { |
if (mode_ != MODE_COMPILE) { |
cerr << "Only one of --encode and --decode can be specified." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
if (!output_directives_.empty() || !descriptor_set_name_.empty()) { |
cerr << "Cannot use " << name |
<< " and generate code or descriptors at the same time." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE; |
@@ -971,10 +1017,10 @@ |
if (name == "--decode") { |
cerr << "To decode an unknown message, use --decode_raw." << endl; |
} |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} else if (!value.empty() && name == "--decode_raw") { |
cerr << "--decode_raw does not take a parameter." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
codec_type_ = value; |
@@ -986,16 +1032,16 @@ |
error_format_ = ERROR_FORMAT_MSVS; |
} else { |
cerr << "Unknown error format: " << value << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
} else if (name == "--plugin") { |
if (plugin_prefix_.empty()) { |
cerr << "This compiler does not support plugins." << endl; |
- return false; |
+ return PARSE_ARGUMENT_FAIL; |
} |
- string name; |
+ string plugin_name; |
string path; |
string::size_type equals_pos = value.find_first_of('='); |
@@ -1003,57 +1049,68 @@ |
// Use the basename of the file. |
string::size_type slash_pos = value.find_last_of('/'); |
if (slash_pos == string::npos) { |
- name = value; |
+ plugin_name = value; |
} else { |
- name = value.substr(slash_pos + 1); |
+ plugin_name = value.substr(slash_pos + 1); |
} |
path = value; |
} else { |
- name = value.substr(0, equals_pos); |
+ plugin_name = value.substr(0, equals_pos); |
path = value.substr(equals_pos + 1); |
} |
- plugins_[name] = path; |
+ plugins_[plugin_name] = path; |
} else { |
// Some other flag. Look it up in the generators list. |
- const GeneratorInfo* generator_info = FindOrNull(generators_, name); |
+ const GeneratorInfo* generator_info = |
+ FindOrNull(generators_by_flag_name_, name); |
if (generator_info == NULL && |
(plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { |
- cerr << "Unknown flag: " << name << endl; |
- return false; |
- } |
+ // Check if it's a generator option flag. |
+ generator_info = FindOrNull(generators_by_option_name_, name); |
+ if (generator_info == NULL) { |
+ cerr << "Unknown flag: " << name << endl; |
+ return PARSE_ARGUMENT_FAIL; |
+ } else { |
+ string* parameters = &generator_parameters_[generator_info->flag_name]; |
+ if (!parameters->empty()) { |
+ parameters->append(","); |
+ } |
+ parameters->append(value); |
+ } |
+ } else { |
+ // It's an output flag. Add it to the output directives. |
+ if (mode_ != MODE_COMPILE) { |
+ cerr << "Cannot use --encode or --decode and generate code at the " |
+ "same time." << endl; |
+ return PARSE_ARGUMENT_FAIL; |
+ } |
- // It's an output flag. Add it to the output directives. |
- if (mode_ != MODE_COMPILE) { |
- cerr << "Cannot use --encode or --decode and generate code at the " |
- "same time." << endl; |
- return false; |
- } |
+ OutputDirective directive; |
+ directive.name = name; |
+ if (generator_info == NULL) { |
+ directive.generator = NULL; |
+ } else { |
+ directive.generator = generator_info->generator; |
+ } |
- OutputDirective directive; |
- directive.name = name; |
- if (generator_info == NULL) { |
- directive.generator = NULL; |
- } else { |
- directive.generator = generator_info->generator; |
- } |
+ // Split value at ':' to separate the generator parameter from the |
+ // filename. However, avoid doing this if the colon is part of a valid |
+ // Windows-style absolute path. |
+ string::size_type colon_pos = value.find_first_of(':'); |
+ if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { |
+ directive.output_location = value; |
+ } else { |
+ directive.parameter = value.substr(0, colon_pos); |
+ directive.output_location = value.substr(colon_pos + 1); |
+ } |
- // Split value at ':' to separate the generator parameter from the |
- // filename. However, avoid doing this if the colon is part of a valid |
- // Windows-style absolute path. |
- string::size_type colon_pos = value.find_first_of(':'); |
- if (colon_pos == string::npos || IsWindowsAbsolutePath(value)) { |
- directive.output_location = value; |
- } else { |
- directive.parameter = value.substr(0, colon_pos); |
- directive.output_location = value.substr(colon_pos + 1); |
+ output_directives_.push_back(directive); |
} |
- |
- output_directives_.push_back(directive); |
} |
- return true; |
+ return PARSE_ARGUMENT_DONE_AND_CONTINUE; |
} |
void CommandLineInterface::PrintHelpText() { |
@@ -1086,6 +1143,12 @@ |
" --include_imports When using --descriptor_set_out, also include\n" |
" all dependencies of the input files in the\n" |
" set, so that the set is self-contained.\n" |
+" --include_source_info When using --descriptor_set_out, do not strip\n" |
+" SourceCodeInfo from the FileDescriptorProto.\n" |
+" This results in vastly larger descriptors that\n" |
+" include information about the original\n" |
+" location of each decl in the source file as\n" |
+" well as surrounding comments.\n" |
" --error_format=FORMAT Set the format in which to print errors.\n" |
" FORMAT may be 'gcc' (the default) or 'msvs'\n" |
" (Microsoft Visual Studio format)." << endl; |
@@ -1101,8 +1164,8 @@ |
" the executable's own name differs." << endl; |
} |
- for (GeneratorMap::iterator iter = generators_.begin(); |
- iter != generators_.end(); ++iter) { |
+ for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); |
+ iter != generators_by_flag_name_.end(); ++iter) { |
// FIXME(kenton): If the text is long enough it will wrap, which is ugly, |
// but fixing this nicely (e.g. splitting on spaces) is probably more |
// trouble than it's worth. |
@@ -1136,10 +1199,16 @@ |
} |
} else { |
// Regular generator. |
+ string parameters = output_directive.parameter; |
+ if (!generator_parameters_[output_directive.name].empty()) { |
+ if (!parameters.empty()) { |
+ parameters.append(","); |
+ } |
+ parameters.append(generator_parameters_[output_directive.name]); |
+ } |
for (int i = 0; i < parsed_files.size(); i++) { |
- if (!output_directive.generator->Generate( |
- parsed_files[i], output_directive.parameter, |
- generator_context, &error)) { |
+ if (!output_directive.generator->Generate(parsed_files[i], parameters, |
+ generator_context, &error)) { |
// Generator returned an error. |
cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " |
<< error << endl; |
@@ -1168,8 +1237,9 @@ |
set<const FileDescriptor*> already_seen; |
for (int i = 0; i < parsed_files.size(); i++) { |
request.add_file_to_generate(parsed_files[i]->name()); |
- GetTransitiveDependencies(parsed_files[i], &already_seen, |
- request.mutable_proto_file()); |
+ GetTransitiveDependencies(parsed_files[i], |
+ true, // Include source code info. |
+ &already_seen, request.mutable_proto_file()); |
} |
// Invoke the plugin. |
@@ -1299,12 +1369,17 @@ |
if (imports_in_descriptor_set_) { |
set<const FileDescriptor*> already_seen; |
for (int i = 0; i < parsed_files.size(); i++) { |
- GetTransitiveDependencies( |
- parsed_files[i], &already_seen, file_set.mutable_file()); |
+ GetTransitiveDependencies(parsed_files[i], |
+ source_info_in_descriptor_set_, |
+ &already_seen, file_set.mutable_file()); |
} |
} else { |
for (int i = 0; i < parsed_files.size(); i++) { |
- parsed_files[i]->CopyTo(file_set.add_file()); |
+ FileDescriptorProto* file_proto = file_set.add_file(); |
+ parsed_files[i]->CopyTo(file_proto); |
+ if (source_info_in_descriptor_set_) { |
+ parsed_files[i]->CopySourceCodeInfoTo(file_proto); |
+ } |
} |
} |
@@ -1334,7 +1409,7 @@ |
} |
void CommandLineInterface::GetTransitiveDependencies( |
- const FileDescriptor* file, |
+ const FileDescriptor* file, bool include_source_code_info, |
set<const FileDescriptor*>* already_seen, |
RepeatedPtrField<FileDescriptorProto>* output) { |
if (!already_seen->insert(file).second) { |
@@ -1344,11 +1419,16 @@ |
// Add all dependencies. |
for (int i = 0; i < file->dependency_count(); i++) { |
- GetTransitiveDependencies(file->dependency(i), already_seen, output); |
+ GetTransitiveDependencies(file->dependency(i), include_source_code_info, |
+ already_seen, output); |
} |
// Add this file. |
- file->CopyTo(output->Add()); |
+ FileDescriptorProto* new_descriptor = output->Add(); |
+ file->CopyTo(new_descriptor); |
+ if (include_source_code_info) { |
+ file->CopySourceCodeInfoTo(new_descriptor); |
+ } |
} |