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 |