// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: [email protected] (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. #ifdef _MSC_VER #include <direct.h> #else #include <unistd.h> #endif #include <errno.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <algorithm> #include <memory> #include <google/protobuf/compiler/importer.h> #include <google/protobuf/compiler/parser.h> #include <google/protobuf/io/tokenizer.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/io/io_win32.h> #ifdef _WIN32 #include <ctype.h> #endif namespace google { namespace protobuf { namespace compiler { #ifdef _WIN32 // DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import // them like we do below. using google::protobuf::io::win32::access; using google::protobuf::io::win32::open; #endif // Returns true if the text looks like a Windows-style absolute path, starting // with a drive letter. Example: "C:\foo". TODO(kenton): Share this with // copy in command_line_interface.cc? static bool IsWindowsAbsolutePath(const std::string& text) { … } MultiFileErrorCollector::~MultiFileErrorCollector() { … } // This class serves two purposes: // - It implements the ErrorCollector interface (used by Tokenizer and Parser) // in terms of MultiFileErrorCollector, using a particular filename. // - It lets us check if any errors have occurred. class SourceTreeDescriptorDatabase::SingleFileErrorCollector : public io::ErrorCollector { … }; // =================================================================== SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase( SourceTree* source_tree) : … { … } SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase( SourceTree* source_tree, DescriptorDatabase* fallback_database) : … { … } SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() { … } bool SourceTreeDescriptorDatabase::FindFileByName(const std::string& filename, FileDescriptorProto* output) { … } bool SourceTreeDescriptorDatabase::FindFileContainingSymbol( const std::string& symbol_name, FileDescriptorProto* output) { … } bool SourceTreeDescriptorDatabase::FindFileContainingExtension( const std::string& containing_type, int field_number, FileDescriptorProto* output) { … } // ------------------------------------------------------------------- SourceTreeDescriptorDatabase::ValidationErrorCollector:: ValidationErrorCollector(SourceTreeDescriptorDatabase* owner) : … { … } SourceTreeDescriptorDatabase::ValidationErrorCollector:: ~ValidationErrorCollector() { … } void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError( const std::string& filename, const std::string& element_name, const Message* descriptor, ErrorLocation location, const std::string& message) { … } void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning( const std::string& filename, const std::string& element_name, const Message* descriptor, ErrorLocation location, const std::string& message) { … } // =================================================================== Importer::Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector) : … { … } Importer::~Importer() { … } const FileDescriptor* Importer::Import(const std::string& filename) { … } void Importer::AddUnusedImportTrackFile(const std::string& file_name, bool is_error) { … } void Importer::ClearUnusedImportTrackFiles() { … } // =================================================================== SourceTree::~SourceTree() { … } std::string SourceTree::GetLastErrorMessage() { … } DiskSourceTree::DiskSourceTree() { … } DiskSourceTree::~DiskSourceTree() { … } static inline char LastChar(const std::string& str) { … } // Given a path, returns an equivalent path with these changes: // - On Windows, any backslashes are replaced with forward slashes. // - Any instances of the directory "." are removed. // - Any consecutive '/'s are collapsed into a single slash. // Note that the resulting string may be empty. // // TODO(kenton): It would be nice to handle "..", e.g. so that we can figure // out that "foo/bar.proto" is inside "baz/../foo". However, if baz is a // symlink or doesn't exist, then things get complicated, and we can't // actually determine this without investigating the filesystem, probably // in non-portable ways. So, we punt. // // TODO(kenton): It would be nice to use realpath() here except that it // resolves symbolic links. This could cause problems if people place // symbolic links in their source tree. For example, if you executed: // protoc --proto_path=foo foo/bar/baz.proto // then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize // to a path which does not appear to be under foo, and thus the compiler // will complain that baz.proto is not inside the --proto_path. static std::string CanonicalizePath(std::string path) { … } static inline bool ContainsParentReference(const std::string& path) { … } // Maps a file from an old location to a new one. Typically, old_prefix is // a virtual path and new_prefix is its corresponding disk path. Returns // false if the filename did not start with old_prefix, otherwise replaces // old_prefix with new_prefix and stores the result in *result. Examples: // string result; // assert(ApplyMapping("foo/bar", "", "baz", &result)); // assert(result == "baz/foo/bar"); // // assert(ApplyMapping("foo/bar", "foo", "baz", &result)); // assert(result == "baz/bar"); // // assert(ApplyMapping("foo", "foo", "bar", &result)); // assert(result == "bar"); // // assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); // assert(!ApplyMapping("foo/bar", "baz", "qux", &result)); // assert(!ApplyMapping("foobar", "foo", "baz", &result)); static bool ApplyMapping(const std::string& filename, const std::string& old_prefix, const std::string& new_prefix, std::string* result) { … } void DiskSourceTree::MapPath(const std::string& virtual_path, const std::string& disk_path) { … } DiskSourceTree::DiskFileToVirtualFileResult DiskSourceTree::DiskFileToVirtualFile(const std::string& disk_file, std::string* virtual_file, std::string* shadowing_disk_file) { … } bool DiskSourceTree::VirtualFileToDiskFile(const std::string& virtual_file, std::string* disk_file) { … } io::ZeroCopyInputStream* DiskSourceTree::Open(const std::string& filename) { … } std::string DiskSourceTree::GetLastErrorMessage() { … } io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( const std::string& virtual_file, std::string* disk_file) { … } io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile( const std::string& filename) { … } } // namespace compiler } // namespace protobuf } // namespace google