| OLD | NEW |
| 1 // Protocol Buffers - Google's data interchange format | 1 // Protocol Buffers - Google's data interchange format |
| 2 // Copyright 2008 Google Inc. All rights reserved. | 2 // Copyright 2008 Google Inc. All rights reserved. |
| 3 // https://developers.google.com/protocol-buffers/ | 3 // https://developers.google.com/protocol-buffers/ |
| 4 // | 4 // |
| 5 // Redistribution and use in source and binary forms, with or without | 5 // Redistribution and use in source and binary forms, with or without |
| 6 // modification, are permitted provided that the following conditions are | 6 // modification, are permitted provided that the following conditions are |
| 7 // met: | 7 // met: |
| 8 // | 8 // |
| 9 // * Redistributions of source code must retain the above copyright | 9 // * Redistributions of source code must retain the above copyright |
| 10 // notice, this list of conditions and the following disclaimer. | 10 // notice, this list of conditions and the following disclaimer. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #include <io.h> | 43 #include <io.h> |
| 44 #include <direct.h> | 44 #include <direct.h> |
| 45 #else | 45 #else |
| 46 #include <unistd.h> | 46 #include <unistd.h> |
| 47 #endif | 47 #endif |
| 48 #include <errno.h> | 48 #include <errno.h> |
| 49 #include <fstream> | 49 #include <fstream> |
| 50 #include <iostream> | 50 #include <iostream> |
| 51 #include <ctype.h> | 51 #include <ctype.h> |
| 52 | 52 |
| 53 #ifdef GOOGLE_PROTOBUF_ARCH_SPARC |
| 53 #include <limits.h> //For PATH_MAX | 54 #include <limits.h> //For PATH_MAX |
| 55 #endif |
| 54 | 56 |
| 55 #include <memory> | 57 #include <memory> |
| 56 #ifndef _SHARED_PTR_H | 58 #ifndef _SHARED_PTR_H |
| 57 #include <google/protobuf/stubs/shared_ptr.h> | 59 #include <google/protobuf/stubs/shared_ptr.h> |
| 58 #endif | 60 #endif |
| 59 | 61 |
| 60 #ifdef __APPLE__ | 62 #ifdef __APPLE__ |
| 61 #include <mach-o/dyld.h> | 63 #include <mach-o/dyld.h> |
| 62 #endif | 64 #endif |
| 63 | 65 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 return true; | 168 return true; |
| 167 } | 169 } |
| 168 } | 170 } |
| 169 | 171 |
| 170 // Try to create the parent directory of the given file, creating the parent's | 172 // Try to create the parent directory of the given file, creating the parent's |
| 171 // parent if necessary, and so on. The full file name is actually | 173 // parent if necessary, and so on. The full file name is actually |
| 172 // (prefix + filename), but we assume |prefix| already exists and only create | 174 // (prefix + filename), but we assume |prefix| already exists and only create |
| 173 // directories listed in |filename|. | 175 // directories listed in |filename|. |
| 174 bool TryCreateParentDirectory(const string& prefix, const string& filename) { | 176 bool TryCreateParentDirectory(const string& prefix, const string& filename) { |
| 175 // Recursively create parent directories to the output file. | 177 // Recursively create parent directories to the output file. |
| 176 std::vector<string> parts = | 178 vector<string> parts = Split(filename, "/", true); |
| 177 Split(filename, "/", true); | |
| 178 string path_so_far = prefix; | 179 string path_so_far = prefix; |
| 179 for (int i = 0; i < parts.size() - 1; i++) { | 180 for (int i = 0; i < parts.size() - 1; i++) { |
| 180 path_so_far += parts[i]; | 181 path_so_far += parts[i]; |
| 181 if (mkdir(path_so_far.c_str(), 0777) != 0) { | 182 if (mkdir(path_so_far.c_str(), 0777) != 0) { |
| 182 if (errno != EEXIST) { | 183 if (errno != EEXIST) { |
| 183 std::cerr << filename << ": while trying to create directory " | 184 std::cerr << filename << ": while trying to create directory " |
| 184 << path_so_far << ": " << strerror(errno) << std::endl; | 185 << path_so_far << ": " << strerror(errno) << std::endl; |
| 185 return false; | 186 return false; |
| 186 } | 187 } |
| 187 } | 188 } |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 pos = path.find_last_of("/\\"); | 257 pos = path.find_last_of("/\\"); |
| 257 if (pos == string::npos || pos == 0) { | 258 if (pos == string::npos || pos == 0) { |
| 258 return; | 259 return; |
| 259 } | 260 } |
| 260 path = path.substr(0, pos); | 261 path = path.substr(0, pos); |
| 261 if (IsInstalledProtoPath(path + "/include")) { | 262 if (IsInstalledProtoPath(path + "/include")) { |
| 262 paths->push_back(pair<string, string>("", path + "/include")); | 263 paths->push_back(pair<string, string>("", path + "/include")); |
| 263 return; | 264 return; |
| 264 } | 265 } |
| 265 } | 266 } |
| 266 | |
| 267 string PluginName(const string& plugin_prefix, const string& directive) { | |
| 268 // Assuming the directive starts with "--" and ends with "_out" or "_opt", | |
| 269 // strip the "--" and "_out/_opt" and add the plugin prefix. | |
| 270 return plugin_prefix + "gen-" + directive.substr(2, directive.size() - 6); | |
| 271 } | |
| 272 } // namespace | 267 } // namespace |
| 273 | 268 |
| 274 // A MultiFileErrorCollector that prints errors to stderr. | 269 // A MultiFileErrorCollector that prints errors to stderr. |
| 275 class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, | 270 class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, |
| 276 public io::ErrorCollector { | 271 public io::ErrorCollector { |
| 277 public: | 272 public: |
| 278 ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) | 273 ErrorPrinter(ErrorFormat format, DiskSourceTree *tree = NULL) |
| 279 : format_(format), tree_(tree) {} | 274 : format_(format), tree_(tree) {} |
| 280 ~ErrorPrinter() {} | 275 ~ErrorPrinter() {} |
| 281 | 276 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 const ErrorFormat format_; | 333 const ErrorFormat format_; |
| 339 DiskSourceTree *tree_; | 334 DiskSourceTree *tree_; |
| 340 }; | 335 }; |
| 341 | 336 |
| 342 // ------------------------------------------------------------------- | 337 // ------------------------------------------------------------------- |
| 343 | 338 |
| 344 // A GeneratorContext implementation that buffers files in memory, then dumps | 339 // A GeneratorContext implementation that buffers files in memory, then dumps |
| 345 // them all to disk on demand. | 340 // them all to disk on demand. |
| 346 class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { | 341 class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { |
| 347 public: | 342 public: |
| 348 GeneratorContextImpl(const std::vector<const FileDescriptor*>& parsed_files); | 343 GeneratorContextImpl(const vector<const FileDescriptor*>& parsed_files); |
| 349 ~GeneratorContextImpl(); | 344 ~GeneratorContextImpl(); |
| 350 | 345 |
| 351 // Write all files in the directory to disk at the given output location, | 346 // Write all files in the directory to disk at the given output location, |
| 352 // which must end in a '/'. | 347 // which must end in a '/'. |
| 353 bool WriteAllToDisk(const string& prefix); | 348 bool WriteAllToDisk(const string& prefix); |
| 354 | 349 |
| 355 // Write the contents of this directory to a ZIP-format archive with the | 350 // Write the contents of this directory to a ZIP-format archive with the |
| 356 // given name. | 351 // given name. |
| 357 bool WriteAllToZip(const string& filename); | 352 bool WriteAllToZip(const string& filename); |
| 358 | 353 |
| 359 // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR | 354 // Add a boilerplate META-INF/MANIFEST.MF file as required by the Java JAR |
| 360 // format, unless one has already been written. | 355 // format, unless one has already been written. |
| 361 void AddJarManifest(); | 356 void AddJarManifest(); |
| 362 | 357 |
| 363 // Get name of all output files. | 358 // Get name of all output files. |
| 364 void GetOutputFilenames(std::vector<string>* output_filenames); | 359 void GetOutputFilenames(vector<string>* output_filenames); |
| 365 | 360 |
| 366 // implements GeneratorContext -------------------------------------- | 361 // implements GeneratorContext -------------------------------------- |
| 367 io::ZeroCopyOutputStream* Open(const string& filename); | 362 io::ZeroCopyOutputStream* Open(const string& filename); |
| 368 io::ZeroCopyOutputStream* OpenForAppend(const string& filename); | 363 io::ZeroCopyOutputStream* OpenForAppend(const string& filename); |
| 369 io::ZeroCopyOutputStream* OpenForInsert( | 364 io::ZeroCopyOutputStream* OpenForInsert( |
| 370 const string& filename, const string& insertion_point); | 365 const string& filename, const string& insertion_point); |
| 371 void ListParsedFiles(std::vector<const FileDescriptor*>* output) { | 366 void ListParsedFiles(vector<const FileDescriptor*>* output) { |
| 372 *output = parsed_files_; | 367 *output = parsed_files_; |
| 373 } | 368 } |
| 374 | 369 |
| 375 private: | 370 private: |
| 376 friend class MemoryOutputStream; | 371 friend class MemoryOutputStream; |
| 377 | 372 |
| 378 // map instead of hash_map so that files are written in order (good when | 373 // map instead of hash_map so that files are written in order (good when |
| 379 // writing zips). | 374 // writing zips). |
| 380 std::map<string, string*> files_; | 375 map<string, string*> files_; |
| 381 const std::vector<const FileDescriptor*>& parsed_files_; | 376 const vector<const FileDescriptor*>& parsed_files_; |
| 382 bool had_error_; | 377 bool had_error_; |
| 383 }; | 378 }; |
| 384 | 379 |
| 385 class CommandLineInterface::MemoryOutputStream | 380 class CommandLineInterface::MemoryOutputStream |
| 386 : public io::ZeroCopyOutputStream { | 381 : public io::ZeroCopyOutputStream { |
| 387 public: | 382 public: |
| 388 MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, | 383 MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, |
| 389 bool append_mode); | 384 bool append_mode); |
| 390 MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, | 385 MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, |
| 391 const string& insertion_point); | 386 const string& insertion_point); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 408 // Whether we should append the output stream to the existing file. | 403 // Whether we should append the output stream to the existing file. |
| 409 bool append_mode_; | 404 bool append_mode_; |
| 410 | 405 |
| 411 // StringOutputStream writing to data_. | 406 // StringOutputStream writing to data_. |
| 412 google::protobuf::scoped_ptr<io::StringOutputStream> inner_; | 407 google::protobuf::scoped_ptr<io::StringOutputStream> inner_; |
| 413 }; | 408 }; |
| 414 | 409 |
| 415 // ------------------------------------------------------------------- | 410 // ------------------------------------------------------------------- |
| 416 | 411 |
| 417 CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl( | 412 CommandLineInterface::GeneratorContextImpl::GeneratorContextImpl( |
| 418 const std::vector<const FileDescriptor*>& parsed_files) | 413 const vector<const FileDescriptor*>& parsed_files) |
| 419 : parsed_files_(parsed_files), | 414 : parsed_files_(parsed_files), |
| 420 had_error_(false) { | 415 had_error_(false) { |
| 421 } | 416 } |
| 422 | 417 |
| 423 CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() { | 418 CommandLineInterface::GeneratorContextImpl::~GeneratorContextImpl() { |
| 424 STLDeleteValues(&files_); | 419 STLDeleteValues(&files_); |
| 425 } | 420 } |
| 426 | 421 |
| 427 bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( | 422 bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( |
| 428 const string& prefix) { | 423 const string& prefix) { |
| 429 if (had_error_) { | 424 if (had_error_) { |
| 430 return false; | 425 return false; |
| 431 } | 426 } |
| 432 | 427 |
| 433 if (!VerifyDirectoryExists(prefix)) { | 428 if (!VerifyDirectoryExists(prefix)) { |
| 434 return false; | 429 return false; |
| 435 } | 430 } |
| 436 | 431 |
| 437 for (std::map<string, string*>::const_iterator iter = files_.begin(); | 432 for (map<string, string*>::const_iterator iter = files_.begin(); |
| 438 iter != files_.end(); ++iter) { | 433 iter != files_.end(); ++iter) { |
| 439 const string& relative_filename = iter->first; | 434 const string& relative_filename = iter->first; |
| 440 const char* data = iter->second->data(); | 435 const char* data = iter->second->data(); |
| 441 int size = iter->second->size(); | 436 int size = iter->second->size(); |
| 442 | 437 |
| 443 if (!TryCreateParentDirectory(prefix, relative_filename)) { | 438 if (!TryCreateParentDirectory(prefix, relative_filename)) { |
| 444 return false; | 439 return false; |
| 445 } | 440 } |
| 446 string filename = prefix + relative_filename; | 441 string filename = prefix + relative_filename; |
| 447 | 442 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 if (file_descriptor < 0) { | 510 if (file_descriptor < 0) { |
| 516 int error = errno; | 511 int error = errno; |
| 517 std::cerr << filename << ": " << strerror(error); | 512 std::cerr << filename << ": " << strerror(error); |
| 518 return false; | 513 return false; |
| 519 } | 514 } |
| 520 | 515 |
| 521 // Create the ZipWriter | 516 // Create the ZipWriter |
| 522 io::FileOutputStream stream(file_descriptor); | 517 io::FileOutputStream stream(file_descriptor); |
| 523 ZipWriter zip_writer(&stream); | 518 ZipWriter zip_writer(&stream); |
| 524 | 519 |
| 525 for (std::map<string, string*>::const_iterator iter = files_.begin(); | 520 for (map<string, string*>::const_iterator iter = files_.begin(); |
| 526 iter != files_.end(); ++iter) { | 521 iter != files_.end(); ++iter) { |
| 527 zip_writer.Write(iter->first, *iter->second); | 522 zip_writer.Write(iter->first, *iter->second); |
| 528 } | 523 } |
| 529 | 524 |
| 530 zip_writer.WriteDirectory(); | 525 zip_writer.WriteDirectory(); |
| 531 | 526 |
| 532 if (stream.GetErrno() != 0) { | 527 if (stream.GetErrno() != 0) { |
| 533 std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; | 528 std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; |
| 534 } | 529 } |
| 535 | 530 |
| 536 if (!stream.Close()) { | 531 if (!stream.Close()) { |
| 537 std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; | 532 std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; |
| 538 } | 533 } |
| 539 | 534 |
| 540 return true; | 535 return true; |
| 541 } | 536 } |
| 542 | 537 |
| 543 void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { | 538 void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { |
| 544 string** map_slot = &files_["META-INF/MANIFEST.MF"]; | 539 string** map_slot = &files_["META-INF/MANIFEST.MF"]; |
| 545 if (*map_slot == NULL) { | 540 if (*map_slot == NULL) { |
| 546 *map_slot = new string( | 541 *map_slot = new string( |
| 547 "Manifest-Version: 1.0\n" | 542 "Manifest-Version: 1.0\n" |
| 548 "Created-By: 1.6.0 (protoc)\n" | 543 "Created-By: 1.6.0 (protoc)\n" |
| 549 "\n"); | 544 "\n"); |
| 550 } | 545 } |
| 551 } | 546 } |
| 552 | 547 |
| 553 void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames( | 548 void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames( |
| 554 std::vector<string>* output_filenames) { | 549 vector<string>* output_filenames) { |
| 555 for (std::map<string, string*>::iterator iter = files_.begin(); | 550 for (map<string, string*>::iterator iter = files_.begin(); |
| 556 iter != files_.end(); ++iter) { | 551 iter != files_.end(); ++iter) { |
| 557 output_filenames->push_back(iter->first); | 552 output_filenames->push_back(iter->first); |
| 558 } | 553 } |
| 559 } | 554 } |
| 560 | 555 |
| 561 io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( | 556 io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( |
| 562 const string& filename) { | 557 const string& filename) { |
| 563 return new MemoryOutputStream(this, filename, false); | 558 return new MemoryOutputStream(this, filename, false); |
| 564 } | 559 } |
| 565 | 560 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 directory_->had_error_ = true; | 607 directory_->had_error_ = true; |
| 613 } | 608 } |
| 614 return; | 609 return; |
| 615 } | 610 } |
| 616 | 611 |
| 617 *map_slot = new string; | 612 *map_slot = new string; |
| 618 (*map_slot)->swap(data_); | 613 (*map_slot)->swap(data_); |
| 619 } else { | 614 } else { |
| 620 // This was an OpenForInsert(). | 615 // This was an OpenForInsert(). |
| 621 | 616 |
| 622 // If the data doesn't end with a clean line break, add one. | 617 // If the data doens't end with a clean line break, add one. |
| 623 if (!data_.empty() && data_[data_.size() - 1] != '\n') { | 618 if (!data_.empty() && data_[data_.size() - 1] != '\n') { |
| 624 data_.push_back('\n'); | 619 data_.push_back('\n'); |
| 625 } | 620 } |
| 626 | 621 |
| 627 // Find the file we are going to insert into. | 622 // Find the file we are going to insert into. |
| 628 if (*map_slot == NULL) { | 623 if (*map_slot == NULL) { |
| 629 std::cerr << filename_ | 624 std::cerr << filename_ |
| 630 << ": Tried to insert into file that doesn't exist." | 625 << ": Tried to insert into file that doesn't exist." |
| 631 << std::endl; | 626 << std::endl; |
| 632 directory_->had_error_ = true; | 627 directory_->had_error_ = true; |
| 633 return; | 628 return; |
| 634 } | 629 } |
| 635 string* target = *map_slot; | 630 string* target = *map_slot; |
| 636 | 631 |
| 637 // Find the insertion point. | 632 // Find the insertion point. |
| 638 string magic_string = strings::Substitute( | 633 string magic_string = strings::Substitute( |
| 639 "@@protoc_insertion_point($0)", insertion_point_); | 634 "@@protoc_insertion_point($0)", insertion_point_); |
| 640 string::size_type pos = target->find(magic_string); | 635 string::size_type pos = target->find(magic_string); |
| 641 | 636 |
| 642 if (pos == string::npos) { | 637 if (pos == string::npos) { |
| 643 std::cerr << filename_ << ": insertion point \"" << insertion_point_ | 638 std::cerr << filename_ << ": insertion point \"" << insertion_point_ |
| 644 << "\" not found." << std::endl; | 639 << "\" not found." << std::endl; |
| 645 directory_->had_error_ = true; | 640 directory_->had_error_ = true; |
| 646 return; | 641 return; |
| 647 } | 642 } |
| 648 | 643 |
| 649 if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) { | 644 // Seek backwards to the beginning of the line, which is where we will |
| 650 // Support for inline "/* @@protoc_insertion_point() */" | 645 // insert the data. Note that this has the effect of pushing the insertion |
| 651 pos = pos - 3; | 646 // point down, so the data is inserted before it. This is intentional |
| 647 // because it means that multiple insertions at the same point will end |
| 648 // up in the expected order in the final output. |
| 649 pos = target->find_last_of('\n', pos); |
| 650 if (pos == string::npos) { |
| 651 // Insertion point is on the first line. |
| 652 pos = 0; |
| 652 } else { | 653 } else { |
| 653 // Seek backwards to the beginning of the line, which is where we will | 654 // Advance to character after '\n'. |
| 654 // insert the data. Note that this has the effect of pushing the | 655 ++pos; |
| 655 // insertion point down, so the data is inserted before it. This is | |
| 656 // intentional because it means that multiple insertions at the same point | |
| 657 // will end up in the expected order in the final output. | |
| 658 pos = target->find_last_of('\n', pos); | |
| 659 if (pos == string::npos) { | |
| 660 // Insertion point is on the first line. | |
| 661 pos = 0; | |
| 662 } else { | |
| 663 // Advance to character after '\n'. | |
| 664 ++pos; | |
| 665 } | |
| 666 } | 656 } |
| 667 | 657 |
| 668 // Extract indent. | 658 // Extract indent. |
| 669 string indent_(*target, pos, target->find_first_not_of(" \t", pos) - pos); | 659 string indent_(*target, pos, target->find_first_not_of(" \t", pos) - pos); |
| 670 | 660 |
| 671 if (indent_.empty()) { | 661 if (indent_.empty()) { |
| 672 // No indent. This makes things easier. | 662 // No indent. This makes things easier. |
| 673 target->insert(pos, data_); | 663 target->insert(pos, data_); |
| 674 } else { | 664 } else { |
| 675 // Calculate how much space we need. | 665 // Calculate how much space we need. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 704 } | 694 } |
| 705 } | 695 } |
| 706 } | 696 } |
| 707 | 697 |
| 708 // =================================================================== | 698 // =================================================================== |
| 709 | 699 |
| 710 CommandLineInterface::CommandLineInterface() | 700 CommandLineInterface::CommandLineInterface() |
| 711 : mode_(MODE_COMPILE), | 701 : mode_(MODE_COMPILE), |
| 712 print_mode_(PRINT_NONE), | 702 print_mode_(PRINT_NONE), |
| 713 error_format_(ERROR_FORMAT_GCC), | 703 error_format_(ERROR_FORMAT_GCC), |
| 714 direct_dependencies_explicitly_set_(false), | |
| 715 imports_in_descriptor_set_(false), | 704 imports_in_descriptor_set_(false), |
| 716 source_info_in_descriptor_set_(false), | 705 source_info_in_descriptor_set_(false), |
| 717 disallow_services_(false), | 706 disallow_services_(false), |
| 718 inputs_are_proto_path_relative_(false) {} | 707 inputs_are_proto_path_relative_(false) {} |
| 719 CommandLineInterface::~CommandLineInterface() {} | 708 CommandLineInterface::~CommandLineInterface() {} |
| 720 | 709 |
| 721 void CommandLineInterface::RegisterGenerator(const string& flag_name, | 710 void CommandLineInterface::RegisterGenerator(const string& flag_name, |
| 722 CodeGenerator* generator, | 711 CodeGenerator* generator, |
| 723 const string& help_text) { | 712 const string& help_text) { |
| 724 GeneratorInfo info; | 713 GeneratorInfo info; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 768 if (!inputs_are_proto_path_relative_) { | 757 if (!inputs_are_proto_path_relative_) { |
| 769 if (!MakeInputsBeProtoPathRelative(&source_tree)) { | 758 if (!MakeInputsBeProtoPathRelative(&source_tree)) { |
| 770 return 1; | 759 return 1; |
| 771 } | 760 } |
| 772 } | 761 } |
| 773 | 762 |
| 774 // Allocate the Importer. | 763 // Allocate the Importer. |
| 775 ErrorPrinter error_collector(error_format_, &source_tree); | 764 ErrorPrinter error_collector(error_format_, &source_tree); |
| 776 Importer importer(&source_tree, &error_collector); | 765 Importer importer(&source_tree, &error_collector); |
| 777 | 766 |
| 778 std::vector<const FileDescriptor*> parsed_files; | 767 vector<const FileDescriptor*> parsed_files; |
| 779 | 768 |
| 780 // Parse each file. | 769 // Parse each file. |
| 781 for (int i = 0; i < input_files_.size(); i++) { | 770 for (int i = 0; i < input_files_.size(); i++) { |
| 782 // Import the file. | 771 // Import the file. |
| 783 importer.AddUnusedImportTrackFile(input_files_[i]); | 772 importer.AddUnusedImportTrackFile(input_files_[i]); |
| 784 const FileDescriptor* parsed_file = importer.Import(input_files_[i]); | 773 const FileDescriptor* parsed_file = importer.Import(input_files_[i]); |
| 785 importer.ClearUnusedImportTrackFiles(); | 774 importer.ClearUnusedImportTrackFiles(); |
| 786 if (parsed_file == NULL) return 1; | 775 if (parsed_file == NULL) return 1; |
| 787 parsed_files.push_back(parsed_file); | 776 parsed_files.push_back(parsed_file); |
| 788 | 777 |
| 789 // Enforce --disallow_services. | 778 // Enforce --disallow_services. |
| 790 if (disallow_services_ && parsed_file->service_count() > 0) { | 779 if (disallow_services_ && parsed_file->service_count() > 0) { |
| 791 cerr << parsed_file->name() << ": This file contains services, but " | 780 cerr << parsed_file->name() << ": This file contains services, but " |
| 792 "--disallow_services was used." << endl; | 781 "--disallow_services was used." << endl; |
| 793 return 1; | 782 return 1; |
| 794 } | 783 } |
| 795 | |
| 796 // Enforce --direct_dependencies | |
| 797 if (direct_dependencies_explicitly_set_) { | |
| 798 bool indirect_imports = false; | |
| 799 for (int i = 0; i < parsed_file->dependency_count(); i++) { | |
| 800 if (direct_dependencies_.find(parsed_file->dependency(i)->name()) == | |
| 801 direct_dependencies_.end()) { | |
| 802 indirect_imports = true; | |
| 803 cerr << parsed_file->name() | |
| 804 << ": File is imported but not declared in " | |
| 805 << "--direct_dependencies: " | |
| 806 << parsed_file->dependency(i)->name() << std::endl; | |
| 807 } | |
| 808 } | |
| 809 if (indirect_imports) { | |
| 810 return 1; | |
| 811 } | |
| 812 } | |
| 813 } | 784 } |
| 814 | 785 |
| 815 // We construct a separate GeneratorContext for each output location. Note | 786 // We construct a separate GeneratorContext for each output location. Note |
| 816 // that two code generators may output to the same location, in which case | 787 // that two code generators may output to the same location, in which case |
| 817 // they should share a single GeneratorContext so that OpenForInsert() works. | 788 // they should share a single GeneratorContext so that OpenForInsert() works. |
| 818 GeneratorContextMap output_directories; | 789 GeneratorContextMap output_directories; |
| 819 | 790 |
| 820 // Generate output. | 791 // Generate output. |
| 821 if (mode_ == MODE_COMPILE) { | 792 if (mode_ == MODE_COMPILE) { |
| 822 for (int i = 0; i < output_directives_.size(); i++) { | 793 for (int i = 0; i < output_directives_.size(); i++) { |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 916 | 887 |
| 917 return 0; | 888 return 0; |
| 918 } | 889 } |
| 919 | 890 |
| 920 void CommandLineInterface::Clear() { | 891 void CommandLineInterface::Clear() { |
| 921 // Clear all members that are set by Run(). Note that we must not clear | 892 // Clear all members that are set by Run(). Note that we must not clear |
| 922 // members which are set by other methods before Run() is called. | 893 // members which are set by other methods before Run() is called. |
| 923 executable_name_.clear(); | 894 executable_name_.clear(); |
| 924 proto_path_.clear(); | 895 proto_path_.clear(); |
| 925 input_files_.clear(); | 896 input_files_.clear(); |
| 926 direct_dependencies_.clear(); | |
| 927 output_directives_.clear(); | 897 output_directives_.clear(); |
| 928 codec_type_.clear(); | 898 codec_type_.clear(); |
| 929 descriptor_set_name_.clear(); | 899 descriptor_set_name_.clear(); |
| 930 dependency_out_name_.clear(); | 900 dependency_out_name_.clear(); |
| 931 | 901 |
| 932 mode_ = MODE_COMPILE; | 902 mode_ = MODE_COMPILE; |
| 933 print_mode_ = PRINT_NONE; | 903 print_mode_ = PRINT_NONE; |
| 934 imports_in_descriptor_set_ = false; | 904 imports_in_descriptor_set_ = false; |
| 935 source_info_in_descriptor_set_ = false; | 905 source_info_in_descriptor_set_ = false; |
| 936 disallow_services_ = false; | 906 disallow_services_ = false; |
| 937 direct_dependencies_explicitly_set_ = false; | |
| 938 } | 907 } |
| 939 | 908 |
| 940 bool CommandLineInterface::MakeInputsBeProtoPathRelative( | 909 bool CommandLineInterface::MakeInputsBeProtoPathRelative( |
| 941 DiskSourceTree* source_tree) { | 910 DiskSourceTree* source_tree) { |
| 942 for (int i = 0; i < input_files_.size(); i++) { | 911 for (int i = 0; i < input_files_.size(); i++) { |
| 943 string virtual_file, shadowing_disk_file; | 912 string virtual_file, shadowing_disk_file; |
| 944 switch (source_tree->DiskFileToVirtualFile( | 913 switch (source_tree->DiskFileToVirtualFile( |
| 945 input_files_[i], &virtual_file, &shadowing_disk_file)) { | 914 input_files_[i], &virtual_file, &shadowing_disk_file)) { |
| 946 case DiskSourceTree::SUCCESS: | 915 case DiskSourceTree::SUCCESS: |
| 947 input_files_[i] = virtual_file; | 916 input_files_[i] = virtual_file; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 978 } | 947 } |
| 979 | 948 |
| 980 return true; | 949 return true; |
| 981 } | 950 } |
| 982 | 951 |
| 983 | 952 |
| 984 CommandLineInterface::ParseArgumentStatus | 953 CommandLineInterface::ParseArgumentStatus |
| 985 CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { | 954 CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { |
| 986 executable_name_ = argv[0]; | 955 executable_name_ = argv[0]; |
| 987 | 956 |
| 988 std::vector<string> arguments; | 957 vector<string> arguments; |
| 989 for (int i = 1; i < argc; ++i) { | 958 for (int i = 1; i < argc; ++i) { |
| 990 arguments.push_back(argv[i]); | 959 arguments.push_back(argv[i]); |
| 991 } | 960 } |
| 992 | 961 |
| 993 // Iterate through all arguments and parse them. | 962 // Iterate through all arguments and parse them. |
| 994 for (int i = 0; i < arguments.size(); ++i) { | 963 for (int i = 0; i < arguments.size(); ++i) { |
| 995 string name, value; | 964 string name, value; |
| 996 | 965 |
| 997 if (ParseArgument(arguments[i].c_str(), &name, &value)) { | 966 if (ParseArgument(arguments[i].c_str(), &name, &value)) { |
| 998 // Returned true => Use the next argument as the flag value. | 967 // Returned true => Use the next argument as the flag value. |
| 999 if (i + 1 == arguments.size() || arguments[i + 1][0] == '-') { | 968 if (i + 1 == arguments.size() || arguments[i + 1][0] == '-') { |
| 1000 std::cerr << "Missing value for flag: " << name << std::endl; | 969 std::cerr << "Missing value for flag: " << name << std::endl; |
| 1001 if (name == "--decode") { | 970 if (name == "--decode") { |
| 1002 std::cerr << "To decode an unknown message, use --decode_raw." | 971 std::cerr << "To decode an unknown message, use --decode_raw." |
| 1003 << std::endl; | 972 << std::endl; |
| 1004 } | 973 } |
| 1005 return PARSE_ARGUMENT_FAIL; | 974 return PARSE_ARGUMENT_FAIL; |
| 1006 } else { | 975 } else { |
| 1007 ++i; | 976 ++i; |
| 1008 value = arguments[i]; | 977 value = arguments[i]; |
| 1009 } | 978 } |
| 1010 } | 979 } |
| 1011 | 980 |
| 1012 ParseArgumentStatus status = InterpretArgument(name, value); | 981 ParseArgumentStatus status = InterpretArgument(name, value); |
| 1013 if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) | 982 if (status != PARSE_ARGUMENT_DONE_AND_CONTINUE) |
| 1014 return status; | 983 return status; |
| 1015 } | 984 } |
| 1016 | 985 |
| 1017 // Make sure each plugin option has a matching plugin output. | |
| 1018 for (map<string, string>::const_iterator i = plugin_parameters_.begin(); | |
| 1019 i != plugin_parameters_.end(); ++i) { | |
| 1020 if (plugins_.find(i->first) == plugins_.end()) { | |
| 1021 std::cerr << "Unknown flag: " | |
| 1022 // strip prefix + "gen-" and add back "_opt" | |
| 1023 << "--" + i->first.substr(plugin_prefix_.size() + 4) + "_opt" | |
| 1024 << std::endl; | |
| 1025 return PARSE_ARGUMENT_FAIL; | |
| 1026 } | |
| 1027 } | |
| 1028 | |
| 1029 // If no --proto_path was given, use the current working directory. | 986 // If no --proto_path was given, use the current working directory. |
| 1030 if (proto_path_.empty()) { | 987 if (proto_path_.empty()) { |
| 1031 // Don't use make_pair as the old/default standard library on Solaris | 988 // Don't use make_pair as the old/default standard library on Solaris |
| 1032 // doesn't support it without explicit template parameters, which are | 989 // doesn't support it without explicit template parameters, which are |
| 1033 // incompatible with C++0x's make_pair. | 990 // incompatible with C++0x's make_pair. |
| 1034 proto_path_.push_back(std::pair<string, string>("", ".")); | 991 proto_path_.push_back(pair<string, string>("", ".")); |
| 1035 } | 992 } |
| 1036 | 993 |
| 1037 // Check some errror cases. | 994 // Check some errror cases. |
| 1038 bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); | 995 bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); |
| 1039 if (decoding_raw && !input_files_.empty()) { | 996 if (decoding_raw && !input_files_.empty()) { |
| 1040 std::cerr << "When using --decode_raw, no input files should be given." | 997 std::cerr << "When using --decode_raw, no input files should be given." |
| 1041 << std::endl; | 998 << std::endl; |
| 1042 return PARSE_ARGUMENT_FAIL; | 999 return PARSE_ARGUMENT_FAIL; |
| 1043 } else if (!decoding_raw && input_files_.empty()) { | 1000 } else if (!decoding_raw && input_files_.empty()) { |
| 1044 std::cerr << "Missing input file." << std::endl; | 1001 std::cerr << "Missing input file." << std::endl; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1147 "input so the program is going to die now." << std::endl; | 1104 "input so the program is going to die now." << std::endl; |
| 1148 return PARSE_ARGUMENT_FAIL; | 1105 return PARSE_ARGUMENT_FAIL; |
| 1149 } | 1106 } |
| 1150 | 1107 |
| 1151 input_files_.push_back(value); | 1108 input_files_.push_back(value); |
| 1152 | 1109 |
| 1153 } else if (name == "-I" || name == "--proto_path") { | 1110 } else if (name == "-I" || name == "--proto_path") { |
| 1154 // Java's -classpath (and some other languages) delimits path components | 1111 // Java's -classpath (and some other languages) delimits path components |
| 1155 // with colons. Let's accept that syntax too just to make things more | 1112 // with colons. Let's accept that syntax too just to make things more |
| 1156 // intuitive. | 1113 // intuitive. |
| 1157 std::vector<string> parts = Split( | 1114 vector<string> parts = Split( |
| 1158 value, kPathSeparator, true); | 1115 value, kPathSeparator, true); |
| 1159 | 1116 |
| 1160 for (int i = 0; i < parts.size(); i++) { | 1117 for (int i = 0; i < parts.size(); i++) { |
| 1161 string virtual_path; | 1118 string virtual_path; |
| 1162 string disk_path; | 1119 string disk_path; |
| 1163 | 1120 |
| 1164 string::size_type equals_pos = parts[i].find_first_of('='); | 1121 string::size_type equals_pos = parts[i].find_first_of('='); |
| 1165 if (equals_pos == string::npos) { | 1122 if (equals_pos == string::npos) { |
| 1166 virtual_path = ""; | 1123 virtual_path = ""; |
| 1167 disk_path = parts[i]; | 1124 disk_path = parts[i]; |
| 1168 } else { | 1125 } else { |
| 1169 virtual_path = parts[i].substr(0, equals_pos); | 1126 virtual_path = parts[i].substr(0, equals_pos); |
| 1170 disk_path = parts[i].substr(equals_pos + 1); | 1127 disk_path = parts[i].substr(equals_pos + 1); |
| 1171 } | 1128 } |
| 1172 | 1129 |
| 1173 if (disk_path.empty()) { | 1130 if (disk_path.empty()) { |
| 1174 std::cerr | 1131 std::cerr |
| 1175 << "--proto_path passed empty directory name. (Use \".\" for " | 1132 << "--proto_path passed empty directory name. (Use \".\" for " |
| 1176 "current directory.)" << std::endl; | 1133 "current directory.)" << std::endl; |
| 1177 return PARSE_ARGUMENT_FAIL; | 1134 return PARSE_ARGUMENT_FAIL; |
| 1178 } | 1135 } |
| 1179 | 1136 |
| 1180 // Make sure disk path exists, warn otherwise. | 1137 // Make sure disk path exists, warn otherwise. |
| 1181 if (access(disk_path.c_str(), F_OK) < 0) { | 1138 if (access(disk_path.c_str(), F_OK) < 0) { |
| 1182 // Try the original path; it may have just happed to have a '=' in it. | 1139 std::cerr << disk_path << ": warning: directory does not exist." |
| 1183 if (access(parts[i].c_str(), F_OK) < 0) { | 1140 << std::endl; |
| 1184 cerr << disk_path << ": warning: directory does not exist." << endl; | |
| 1185 } else { | |
| 1186 virtual_path = ""; | |
| 1187 disk_path = parts[i]; | |
| 1188 } | |
| 1189 } | 1141 } |
| 1190 | 1142 |
| 1191 // Don't use make_pair as the old/default standard library on Solaris | 1143 // Don't use make_pair as the old/default standard library on Solaris |
| 1192 // doesn't support it without explicit template parameters, which are | 1144 // doesn't support it without explicit template parameters, which are |
| 1193 // incompatible with C++0x's make_pair. | 1145 // incompatible with C++0x's make_pair. |
| 1194 proto_path_.push_back(std::pair<string, string>(virtual_path, disk_path)); | 1146 proto_path_.push_back(pair<string, string>(virtual_path, disk_path)); |
| 1195 } | 1147 } |
| 1196 | 1148 |
| 1197 } else if (name == "--direct_dependencies") { | |
| 1198 if (direct_dependencies_explicitly_set_) { | |
| 1199 std::cerr << name << " may only be passed once. To specify multiple " | |
| 1200 "direct dependencies, pass them all as a single " | |
| 1201 "parameter separated by ':'." | |
| 1202 << std::endl; | |
| 1203 return PARSE_ARGUMENT_FAIL; | |
| 1204 } | |
| 1205 | |
| 1206 direct_dependencies_explicitly_set_ = true; | |
| 1207 std::vector<string> direct = Split( | |
| 1208 value, ":", true); | |
| 1209 GOOGLE_DCHECK(direct_dependencies_.empty()); | |
| 1210 direct_dependencies_.insert(direct.begin(), direct.end()); | |
| 1211 | |
| 1212 } else if (name == "-o" || name == "--descriptor_set_out") { | 1149 } else if (name == "-o" || name == "--descriptor_set_out") { |
| 1213 if (!descriptor_set_name_.empty()) { | 1150 if (!descriptor_set_name_.empty()) { |
| 1214 std::cerr << name << " may only be passed once." << std::endl; | 1151 std::cerr << name << " may only be passed once." << std::endl; |
| 1215 return PARSE_ARGUMENT_FAIL; | 1152 return PARSE_ARGUMENT_FAIL; |
| 1216 } | 1153 } |
| 1217 if (value.empty()) { | 1154 if (value.empty()) { |
| 1218 std::cerr << name << " requires a non-empty value." << std::endl; | 1155 std::cerr << name << " requires a non-empty value." << std::endl; |
| 1219 return PARSE_ARGUMENT_FAIL; | 1156 return PARSE_ARGUMENT_FAIL; |
| 1220 } | 1157 } |
| 1221 if (mode_ != MODE_COMPILE) { | 1158 if (mode_ != MODE_COMPILE) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1349 mode_ = MODE_PRINT; | 1286 mode_ = MODE_PRINT; |
| 1350 print_mode_ = PRINT_FREE_FIELDS; | 1287 print_mode_ = PRINT_FREE_FIELDS; |
| 1351 } else { | 1288 } else { |
| 1352 // Some other flag. Look it up in the generators list. | 1289 // Some other flag. Look it up in the generators list. |
| 1353 const GeneratorInfo* generator_info = | 1290 const GeneratorInfo* generator_info = |
| 1354 FindOrNull(generators_by_flag_name_, name); | 1291 FindOrNull(generators_by_flag_name_, name); |
| 1355 if (generator_info == NULL && | 1292 if (generator_info == NULL && |
| 1356 (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { | 1293 (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) { |
| 1357 // Check if it's a generator option flag. | 1294 // Check if it's a generator option flag. |
| 1358 generator_info = FindOrNull(generators_by_option_name_, name); | 1295 generator_info = FindOrNull(generators_by_option_name_, name); |
| 1359 if (generator_info != NULL) { | 1296 if (generator_info == NULL) { |
| 1297 std::cerr << "Unknown flag: " << name << std::endl; |
| 1298 return PARSE_ARGUMENT_FAIL; |
| 1299 } else { |
| 1360 string* parameters = &generator_parameters_[generator_info->flag_name]; | 1300 string* parameters = &generator_parameters_[generator_info->flag_name]; |
| 1361 if (!parameters->empty()) { | 1301 if (!parameters->empty()) { |
| 1362 parameters->append(","); | 1302 parameters->append(","); |
| 1363 } | 1303 } |
| 1364 parameters->append(value); | 1304 parameters->append(value); |
| 1365 } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) { | |
| 1366 string* parameters = | |
| 1367 &plugin_parameters_[PluginName(plugin_prefix_, name)]; | |
| 1368 if (!parameters->empty()) { | |
| 1369 parameters->append(","); | |
| 1370 } | |
| 1371 parameters->append(value); | |
| 1372 } else { | |
| 1373 std::cerr << "Unknown flag: " << name << std::endl; | |
| 1374 return PARSE_ARGUMENT_FAIL; | |
| 1375 } | 1305 } |
| 1376 } else { | 1306 } else { |
| 1377 // It's an output flag. Add it to the output directives. | 1307 // It's an output flag. Add it to the output directives. |
| 1378 if (mode_ != MODE_COMPILE) { | 1308 if (mode_ != MODE_COMPILE) { |
| 1379 std::cerr << "Cannot use --encode, --decode or print .proto info and " | 1309 std::cerr << "Cannot use --encode, --decode or print .proto info and " |
| 1380 "generate code at the same time." << std::endl; | 1310 "generate code at the same time." << std::endl; |
| 1381 return PARSE_ARGUMENT_FAIL; | 1311 return PARSE_ARGUMENT_FAIL; |
| 1382 } | 1312 } |
| 1383 | 1313 |
| 1384 OutputDirective directive; | 1314 OutputDirective directive; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 // FIXME(kenton): If the text is long enough it will wrap, which is ugly, | 1402 // FIXME(kenton): If the text is long enough it will wrap, which is ugly, |
| 1473 // but fixing this nicely (e.g. splitting on spaces) is probably more | 1403 // but fixing this nicely (e.g. splitting on spaces) is probably more |
| 1474 // trouble than it's worth. | 1404 // trouble than it's worth. |
| 1475 std::cerr << " " << iter->first << "=OUT_DIR " | 1405 std::cerr << " " << iter->first << "=OUT_DIR " |
| 1476 << string(19 - iter->first.size(), ' ') // Spaces for alignment. | 1406 << string(19 - iter->first.size(), ' ') // Spaces for alignment. |
| 1477 << iter->second.help_text << std::endl; | 1407 << iter->second.help_text << std::endl; |
| 1478 } | 1408 } |
| 1479 } | 1409 } |
| 1480 | 1410 |
| 1481 bool CommandLineInterface::GenerateOutput( | 1411 bool CommandLineInterface::GenerateOutput( |
| 1482 const std::vector<const FileDescriptor*>& parsed_files, | 1412 const vector<const FileDescriptor*>& parsed_files, |
| 1483 const OutputDirective& output_directive, | 1413 const OutputDirective& output_directive, |
| 1484 GeneratorContext* generator_context) { | 1414 GeneratorContext* generator_context) { |
| 1485 // Call the generator. | 1415 // Call the generator. |
| 1486 string error; | 1416 string error; |
| 1487 if (output_directive.generator == NULL) { | 1417 if (output_directive.generator == NULL) { |
| 1488 // This is a plugin. | 1418 // This is a plugin. |
| 1489 GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") && | 1419 GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") && |
| 1490 HasSuffixString(output_directive.name, "_out")) | 1420 HasSuffixString(output_directive.name, "_out")) |
| 1491 << "Bad name for plugin generator: " << output_directive.name; | 1421 << "Bad name for plugin generator: " << output_directive.name; |
| 1492 | 1422 |
| 1493 string plugin_name = PluginName(plugin_prefix_ , output_directive.name); | 1423 // Strip the "--" and "_out" and add the plugin prefix. |
| 1494 string parameters = output_directive.parameter; | 1424 string plugin_name = plugin_prefix_ + "gen-" + |
| 1495 if (!plugin_parameters_[plugin_name].empty()) { | 1425 output_directive.name.substr(2, output_directive.name.size() - 6); |
| 1496 if (!parameters.empty()) { | 1426 |
| 1497 parameters.append(","); | |
| 1498 } | |
| 1499 parameters.append(plugin_parameters_[plugin_name]); | |
| 1500 } | |
| 1501 if (!GeneratePluginOutput(parsed_files, plugin_name, | 1427 if (!GeneratePluginOutput(parsed_files, plugin_name, |
| 1502 parameters, | 1428 output_directive.parameter, |
| 1503 generator_context, &error)) { | 1429 generator_context, &error)) { |
| 1504 std::cerr << output_directive.name << ": " << error << std::endl; | 1430 std::cerr << output_directive.name << ": " << error << std::endl; |
| 1505 return false; | 1431 return false; |
| 1506 } | 1432 } |
| 1507 } else { | 1433 } else { |
| 1508 // Regular generator. | 1434 // Regular generator. |
| 1509 string parameters = output_directive.parameter; | 1435 string parameters = output_directive.parameter; |
| 1510 if (!generator_parameters_[output_directive.name].empty()) { | 1436 if (!generator_parameters_[output_directive.name].empty()) { |
| 1511 if (!parameters.empty()) { | 1437 if (!parameters.empty()) { |
| 1512 parameters.append(","); | 1438 parameters.append(","); |
| 1513 } | 1439 } |
| 1514 parameters.append(generator_parameters_[output_directive.name]); | 1440 parameters.append(generator_parameters_[output_directive.name]); |
| 1515 } | 1441 } |
| 1516 if (!output_directive.generator->GenerateAll( | 1442 if (output_directive.generator->HasGenerateAll()) { |
| 1517 parsed_files, parameters, generator_context, &error)) { | 1443 if (!output_directive.generator->GenerateAll( |
| 1518 // Generator returned an error. | 1444 parsed_files, parameters, generator_context, &error)) { |
| 1519 std::cerr << output_directive.name << ": " << error << std::endl; | 1445 // Generator returned an error. |
| 1520 return false; | 1446 std::cerr << output_directive.name << ": " |
| 1447 << ": " << error << std::endl; |
| 1448 return false; |
| 1449 } |
| 1450 } else { |
| 1451 for (int i = 0; i < parsed_files.size(); i++) { |
| 1452 if (!output_directive.generator->Generate(parsed_files[i], parameters, |
| 1453 generator_context, &error)) { |
| 1454 // Generator returned an error. |
| 1455 std::cerr << output_directive.name << ": " << parsed_files[i]->name() |
| 1456 << ": " << error << std::endl; |
| 1457 return false; |
| 1458 } |
| 1459 } |
| 1521 } | 1460 } |
| 1522 } | 1461 } |
| 1523 | 1462 |
| 1524 return true; | 1463 return true; |
| 1525 } | 1464 } |
| 1526 | 1465 |
| 1527 bool CommandLineInterface::GenerateDependencyManifestFile( | 1466 bool CommandLineInterface::GenerateDependencyManifestFile( |
| 1528 const std::vector<const FileDescriptor*>& parsed_files, | 1467 const vector<const FileDescriptor*>& parsed_files, |
| 1529 const GeneratorContextMap& output_directories, | 1468 const GeneratorContextMap& output_directories, |
| 1530 DiskSourceTree* source_tree) { | 1469 DiskSourceTree* source_tree) { |
| 1531 FileDescriptorSet file_set; | 1470 FileDescriptorSet file_set; |
| 1532 | 1471 |
| 1533 std::set<const FileDescriptor*> already_seen; | 1472 set<const FileDescriptor*> already_seen; |
| 1534 for (int i = 0; i < parsed_files.size(); i++) { | 1473 for (int i = 0; i < parsed_files.size(); i++) { |
| 1535 GetTransitiveDependencies(parsed_files[i], | 1474 GetTransitiveDependencies(parsed_files[i], |
| 1536 false, | 1475 false, |
| 1537 false, | 1476 false, |
| 1538 &already_seen, | 1477 &already_seen, |
| 1539 file_set.mutable_file()); | 1478 file_set.mutable_file()); |
| 1540 } | 1479 } |
| 1541 | 1480 |
| 1542 std::vector<string> output_filenames; | 1481 vector<string> output_filenames; |
| 1543 for (GeneratorContextMap::const_iterator iter = output_directories.begin(); | 1482 for (GeneratorContextMap::const_iterator iter = output_directories.begin(); |
| 1544 iter != output_directories.end(); ++iter) { | 1483 iter != output_directories.end(); ++iter) { |
| 1545 const string& location = iter->first; | 1484 const string& location = iter->first; |
| 1546 GeneratorContextImpl* directory = iter->second; | 1485 GeneratorContextImpl* directory = iter->second; |
| 1547 std::vector<string> relative_output_filenames; | 1486 vector<string> relative_output_filenames; |
| 1548 directory->GetOutputFilenames(&relative_output_filenames); | 1487 directory->GetOutputFilenames(&relative_output_filenames); |
| 1549 for (int i = 0; i < relative_output_filenames.size(); i++) { | 1488 for (int i = 0; i < relative_output_filenames.size(); i++) { |
| 1550 string output_filename = location + relative_output_filenames[i]; | 1489 string output_filename = location + relative_output_filenames[i]; |
| 1551 if (output_filename.compare(0, 2, "./") == 0) { | 1490 if (output_filename.compare(0, 2, "./") == 0) { |
| 1552 output_filename = output_filename.substr(2); | 1491 output_filename = output_filename.substr(2); |
| 1553 } | 1492 } |
| 1554 output_filenames.push_back(output_filename); | 1493 output_filenames.push_back(output_filename); |
| 1555 } | 1494 } |
| 1556 } | 1495 } |
| 1557 | 1496 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1590 std::cerr << "Unable to identify path for file " << virtual_file | 1529 std::cerr << "Unable to identify path for file " << virtual_file |
| 1591 << std::endl; | 1530 << std::endl; |
| 1592 return false; | 1531 return false; |
| 1593 } | 1532 } |
| 1594 } | 1533 } |
| 1595 | 1534 |
| 1596 return true; | 1535 return true; |
| 1597 } | 1536 } |
| 1598 | 1537 |
| 1599 bool CommandLineInterface::GeneratePluginOutput( | 1538 bool CommandLineInterface::GeneratePluginOutput( |
| 1600 const std::vector<const FileDescriptor*>& parsed_files, | 1539 const vector<const FileDescriptor*>& parsed_files, |
| 1601 const string& plugin_name, | 1540 const string& plugin_name, |
| 1602 const string& parameter, | 1541 const string& parameter, |
| 1603 GeneratorContext* generator_context, | 1542 GeneratorContext* generator_context, |
| 1604 string* error) { | 1543 string* error) { |
| 1605 CodeGeneratorRequest request; | 1544 CodeGeneratorRequest request; |
| 1606 CodeGeneratorResponse response; | 1545 CodeGeneratorResponse response; |
| 1607 | 1546 |
| 1608 // Build the request. | 1547 // Build the request. |
| 1609 if (!parameter.empty()) { | 1548 if (!parameter.empty()) { |
| 1610 request.set_parameter(parameter); | 1549 request.set_parameter(parameter); |
| 1611 } | 1550 } |
| 1612 | 1551 |
| 1613 std::set<const FileDescriptor*> already_seen; | 1552 set<const FileDescriptor*> already_seen; |
| 1614 for (int i = 0; i < parsed_files.size(); i++) { | 1553 for (int i = 0; i < parsed_files.size(); i++) { |
| 1615 request.add_file_to_generate(parsed_files[i]->name()); | 1554 request.add_file_to_generate(parsed_files[i]->name()); |
| 1616 GetTransitiveDependencies(parsed_files[i], | 1555 GetTransitiveDependencies(parsed_files[i], |
| 1617 true, // Include json_name for plugins. | 1556 true, // Include json_name for plugins. |
| 1618 true, // Include source code info. | 1557 true, // Include source code info. |
| 1619 &already_seen, request.mutable_proto_file()); | 1558 &already_seen, request.mutable_proto_file()); |
| 1620 } | 1559 } |
| 1621 | 1560 |
| 1622 google::protobuf::compiler::Version* version = | |
| 1623 request.mutable_compiler_version(); | |
| 1624 version->set_major(GOOGLE_PROTOBUF_VERSION / 1000000); | |
| 1625 version->set_minor(GOOGLE_PROTOBUF_VERSION / 1000 % 1000); | |
| 1626 version->set_patch(GOOGLE_PROTOBUF_VERSION % 1000); | |
| 1627 version->set_suffix(GOOGLE_PROTOBUF_VERSION_SUFFIX); | |
| 1628 | |
| 1629 // Invoke the plugin. | 1561 // Invoke the plugin. |
| 1630 Subprocess subprocess; | 1562 Subprocess subprocess; |
| 1631 | 1563 |
| 1632 if (plugins_.count(plugin_name) > 0) { | 1564 if (plugins_.count(plugin_name) > 0) { |
| 1633 subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME); | 1565 subprocess.Start(plugins_[plugin_name], Subprocess::EXACT_NAME); |
| 1634 } else { | 1566 } else { |
| 1635 subprocess.Start(plugin_name, Subprocess::SEARCH_PATH); | 1567 subprocess.Start(plugin_name, Subprocess::SEARCH_PATH); |
| 1636 } | 1568 } |
| 1637 | 1569 |
| 1638 string communicate_error; | 1570 string communicate_error; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1740 if (!TextFormat::Print(*message, &out)) { | 1672 if (!TextFormat::Print(*message, &out)) { |
| 1741 std::cerr << "output: I/O error." << std::endl; | 1673 std::cerr << "output: I/O error." << std::endl; |
| 1742 return false; | 1674 return false; |
| 1743 } | 1675 } |
| 1744 } | 1676 } |
| 1745 | 1677 |
| 1746 return true; | 1678 return true; |
| 1747 } | 1679 } |
| 1748 | 1680 |
| 1749 bool CommandLineInterface::WriteDescriptorSet( | 1681 bool CommandLineInterface::WriteDescriptorSet( |
| 1750 const std::vector<const FileDescriptor*> parsed_files) { | 1682 const vector<const FileDescriptor*> parsed_files) { |
| 1751 FileDescriptorSet file_set; | 1683 FileDescriptorSet file_set; |
| 1752 | 1684 |
| 1753 if (imports_in_descriptor_set_) { | 1685 if (imports_in_descriptor_set_) { |
| 1754 std::set<const FileDescriptor*> already_seen; | 1686 set<const FileDescriptor*> already_seen; |
| 1755 for (int i = 0; i < parsed_files.size(); i++) { | 1687 for (int i = 0; i < parsed_files.size(); i++) { |
| 1756 GetTransitiveDependencies(parsed_files[i], | 1688 GetTransitiveDependencies(parsed_files[i], |
| 1757 true, // Include json_name | 1689 true, // Include json_name |
| 1758 source_info_in_descriptor_set_, | 1690 source_info_in_descriptor_set_, |
| 1759 &already_seen, file_set.mutable_file()); | 1691 &already_seen, file_set.mutable_file()); |
| 1760 } | 1692 } |
| 1761 } else { | 1693 } else { |
| 1762 std::set<const FileDescriptor*> already_seen; | 1694 set<const FileDescriptor*> already_seen; |
| 1763 for (int i = 0; i < parsed_files.size(); i++) { | 1695 for (int i = 0; i < parsed_files.size(); i++) { |
| 1764 if (!already_seen.insert(parsed_files[i]).second) { | 1696 if (!already_seen.insert(parsed_files[i]).second) { |
| 1765 continue; | 1697 continue; |
| 1766 } | 1698 } |
| 1767 FileDescriptorProto* file_proto = file_set.add_file(); | 1699 FileDescriptorProto* file_proto = file_set.add_file(); |
| 1768 parsed_files[i]->CopyTo(file_proto); | 1700 parsed_files[i]->CopyTo(file_proto); |
| 1769 parsed_files[i]->CopyJsonNameTo(file_proto); | 1701 parsed_files[i]->CopyJsonNameTo(file_proto); |
| 1770 if (source_info_in_descriptor_set_) { | 1702 if (source_info_in_descriptor_set_) { |
| 1771 parsed_files[i]->CopySourceCodeInfoTo(file_proto); | 1703 parsed_files[i]->CopySourceCodeInfoTo(file_proto); |
| 1772 } | 1704 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1797 return false; | 1729 return false; |
| 1798 } | 1730 } |
| 1799 | 1731 |
| 1800 return true; | 1732 return true; |
| 1801 } | 1733 } |
| 1802 | 1734 |
| 1803 void CommandLineInterface::GetTransitiveDependencies( | 1735 void CommandLineInterface::GetTransitiveDependencies( |
| 1804 const FileDescriptor* file, | 1736 const FileDescriptor* file, |
| 1805 bool include_json_name, | 1737 bool include_json_name, |
| 1806 bool include_source_code_info, | 1738 bool include_source_code_info, |
| 1807 std::set<const FileDescriptor*>* already_seen, | 1739 set<const FileDescriptor*>* already_seen, |
| 1808 RepeatedPtrField<FileDescriptorProto>* output) { | 1740 RepeatedPtrField<FileDescriptorProto>* output) { |
| 1809 if (!already_seen->insert(file).second) { | 1741 if (!already_seen->insert(file).second) { |
| 1810 // Already saw this file. Skip. | 1742 // Already saw this file. Skip. |
| 1811 return; | 1743 return; |
| 1812 } | 1744 } |
| 1813 | 1745 |
| 1814 // Add all dependencies. | 1746 // Add all dependencies. |
| 1815 for (int i = 0; i < file->dependency_count(); i++) { | 1747 for (int i = 0; i < file->dependency_count(); i++) { |
| 1816 GetTransitiveDependencies(file->dependency(i), | 1748 GetTransitiveDependencies(file->dependency(i), |
| 1817 include_json_name, | 1749 include_json_name, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 // message NestedBaz {} | 1788 // message NestedBaz {} |
| 1857 // } | 1789 // } |
| 1858 // } | 1790 // } |
| 1859 // | 1791 // |
| 1860 // In this case, Bar, Quz and NestedBaz will be added into the nested types. | 1792 // In this case, Bar, Quz and NestedBaz will be added into the nested types. |
| 1861 // Since free field numbers of group types will not be printed, this makes sure | 1793 // Since free field numbers of group types will not be printed, this makes sure |
| 1862 // the nested message types in groups will not be dropped. The nested_messages | 1794 // the nested message types in groups will not be dropped. The nested_messages |
| 1863 // parameter will contain the direct children (when groups are ignored in the | 1795 // parameter will contain the direct children (when groups are ignored in the |
| 1864 // tree) of the given descriptor for the caller to traverse. The declaration | 1796 // tree) of the given descriptor for the caller to traverse. The declaration |
| 1865 // order of the nested messages is also preserved. | 1797 // order of the nested messages is also preserved. |
| 1866 typedef std::pair<int, int> FieldRange; | 1798 typedef pair<int, int> FieldRange; |
| 1867 void GatherOccupiedFieldRanges( | 1799 void GatherOccupiedFieldRanges(const Descriptor* descriptor, |
| 1868 const Descriptor* descriptor, std::set<FieldRange>* ranges, | 1800 set<FieldRange>* ranges, |
| 1869 std::vector<const Descriptor*>* nested_messages) { | 1801 vector<const Descriptor*>* nested_messages) { |
| 1870 std::set<const Descriptor*> groups; | 1802 set<const Descriptor*> groups; |
| 1871 for (int i = 0; i < descriptor->field_count(); ++i) { | 1803 for (int i = 0; i < descriptor->field_count(); ++i) { |
| 1872 const FieldDescriptor* fd = descriptor->field(i); | 1804 const FieldDescriptor* fd = descriptor->field(i); |
| 1873 ranges->insert(FieldRange(fd->number(), fd->number() + 1)); | 1805 ranges->insert(FieldRange(fd->number(), fd->number() + 1)); |
| 1874 if (fd->type() == FieldDescriptor::TYPE_GROUP) { | 1806 if (fd->type() == FieldDescriptor::TYPE_GROUP) { |
| 1875 groups.insert(fd->message_type()); | 1807 groups.insert(fd->message_type()); |
| 1876 } | 1808 } |
| 1877 } | 1809 } |
| 1878 for (int i = 0; i < descriptor->extension_range_count(); ++i) { | 1810 for (int i = 0; i < descriptor->extension_range_count(); ++i) { |
| 1879 ranges->insert(FieldRange(descriptor->extension_range(i)->start, | 1811 ranges->insert(FieldRange(descriptor->extension_range(i)->start, |
| 1880 descriptor->extension_range(i)->end)); | 1812 descriptor->extension_range(i)->end)); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1892 } else { | 1824 } else { |
| 1893 nested_messages->push_back(nested_desc); | 1825 nested_messages->push_back(nested_desc); |
| 1894 } | 1826 } |
| 1895 } | 1827 } |
| 1896 } | 1828 } |
| 1897 | 1829 |
| 1898 // Utility function for PrintFreeFieldNumbers. | 1830 // Utility function for PrintFreeFieldNumbers. |
| 1899 // Actually prints the formatted free field numbers for given message name and | 1831 // Actually prints the formatted free field numbers for given message name and |
| 1900 // occupied ranges. | 1832 // occupied ranges. |
| 1901 void FormatFreeFieldNumbers(const string& name, | 1833 void FormatFreeFieldNumbers(const string& name, |
| 1902 const std::set<FieldRange>& ranges) { | 1834 const set<FieldRange>& ranges) { |
| 1903 string output; | 1835 string output; |
| 1904 StringAppendF(&output, "%-35s free:", name.c_str()); | 1836 StringAppendF(&output, "%-35s free:", name.c_str()); |
| 1905 int next_free_number = 1; | 1837 int next_free_number = 1; |
| 1906 for (std::set<FieldRange>::const_iterator i = ranges.begin(); | 1838 for (set<FieldRange>::const_iterator i = ranges.begin(); |
| 1907 i != ranges.end(); ++i) { | 1839 i != ranges.end(); ++i) { |
| 1908 // This happens when groups re-use parent field numbers, in which | 1840 // This happens when groups re-use parent field numbers, in which |
| 1909 // case we skip the FieldRange entirely. | 1841 // case we skip the FieldRange entirely. |
| 1910 if (next_free_number >= i->second) continue; | 1842 if (next_free_number >= i->second) continue; |
| 1911 | 1843 |
| 1912 if (next_free_number < i->first) { | 1844 if (next_free_number < i->first) { |
| 1913 if (next_free_number + 1 == i->first) { | 1845 if (next_free_number + 1 == i->first) { |
| 1914 // Singleton | 1846 // Singleton |
| 1915 StringAppendF(&output, " %d", next_free_number); | 1847 StringAppendF(&output, " %d", next_free_number); |
| 1916 } else { | 1848 } else { |
| 1917 // Range | 1849 // Range |
| 1918 StringAppendF(&output, " %d-%d", next_free_number, i->first - 1); | 1850 StringAppendF(&output, " %d-%d", next_free_number, i->first - 1); |
| 1919 } | 1851 } |
| 1920 } | 1852 } |
| 1921 next_free_number = i->second; | 1853 next_free_number = i->second; |
| 1922 } | 1854 } |
| 1923 if (next_free_number <= FieldDescriptor::kMaxNumber) { | 1855 if (next_free_number <= FieldDescriptor::kMaxNumber) { |
| 1924 StringAppendF(&output, " %d-INF", next_free_number); | 1856 StringAppendF(&output, " %d-INF", next_free_number); |
| 1925 } | 1857 } |
| 1926 std::cout << output << std::endl; | 1858 std::cout << output << std::endl; |
| 1927 } | 1859 } |
| 1928 | 1860 |
| 1929 } // namespace | 1861 } // namespace |
| 1930 | 1862 |
| 1931 void CommandLineInterface::PrintFreeFieldNumbers( | 1863 void CommandLineInterface::PrintFreeFieldNumbers( |
| 1932 const Descriptor* descriptor) { | 1864 const Descriptor* descriptor) { |
| 1933 std::set<FieldRange> ranges; | 1865 set<FieldRange> ranges; |
| 1934 std::vector<const Descriptor*> nested_messages; | 1866 vector<const Descriptor*> nested_messages; |
| 1935 GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages); | 1867 GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages); |
| 1936 | 1868 |
| 1937 for (int i = 0; i < nested_messages.size(); ++i) { | 1869 for (int i = 0; i < nested_messages.size(); ++i) { |
| 1938 PrintFreeFieldNumbers(nested_messages[i]); | 1870 PrintFreeFieldNumbers(nested_messages[i]); |
| 1939 } | 1871 } |
| 1940 FormatFreeFieldNumbers(descriptor->full_name(), ranges); | 1872 FormatFreeFieldNumbers(descriptor->full_name(), ranges); |
| 1941 } | 1873 } |
| 1942 | 1874 |
| 1943 | 1875 |
| 1944 | 1876 |
| 1945 } // namespace compiler | 1877 } // namespace compiler |
| 1946 } // namespace protobuf | 1878 } // namespace protobuf |
| 1947 } // namespace google | 1879 } // namespace google |
| OLD | NEW |