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