1 //===-- include/flang/Parser/source.h ---------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_PARSER_SOURCE_H_ 10 #define FORTRAN_PARSER_SOURCE_H_ 11 12 // Source file content is lightly normalized when the file is read. 13 // - Line ending markers are converted to single newline characters 14 // - A newline character is added to the last line of the file if one is needed 15 // - A Unicode byte order mark is recognized if present. 16 17 #include "characters.h" 18 #include "flang/Common/reference.h" 19 #include "llvm/Support/MemoryBuffer.h" 20 #include "llvm/Support/raw_ostream.h" 21 #include <cstddef> 22 #include <list> 23 #include <map> 24 #include <optional> 25 #include <set> 26 #include <string> 27 #include <utility> 28 #include <vector> 29 30 namespace llvm { 31 class raw_ostream; 32 } 33 34 namespace Fortran::parser { 35 36 std::string DirectoryName(std::string path); 37 std::optional<std::string> LocateSourceFile( 38 std::string name, const std::list<std::string> &searchPath); 39 std::vector<std::string> LocateSourceFileAll( 40 std::string name, const std::vector<std::string> &searchPath); 41 42 class SourceFile; 43 44 struct SourcePosition { 45 common::Reference<const SourceFile> sourceFile; 46 common::Reference<const std::string> 47 path; // may not be sourceFile.path() when #line present 48 int line, column; 49 int trueLineNumber; 50 }; 51 52 class SourceFile { 53 public: SourceFile(Encoding e)54 explicit SourceFile(Encoding e) : encoding_{e} {} 55 ~SourceFile(); path()56 const std::string &path() const { return path_; } content()57 llvm::ArrayRef<char> content() const { 58 return buf_->getBuffer().slice(bom_end_, buf_end_ - bom_end_); 59 } bytes()60 std::size_t bytes() const { return content().size(); } lines()61 std::size_t lines() const { return lineStart_.size(); } encoding()62 Encoding encoding() const { return encoding_; } 63 64 bool Open(std::string path, llvm::raw_ostream &error); 65 bool ReadStandardInput(llvm::raw_ostream &error); 66 void Close(); 67 SourcePosition GetSourcePosition(std::size_t) const; GetLineStartOffset(int lineNumber)68 std::size_t GetLineStartOffset(int lineNumber) const { 69 return lineStart_.at(lineNumber - 1); 70 } 71 const std::string &SavePath(std::string &&); 72 void LineDirective(int trueLineNumber, const std::string &, int); 73 llvm::raw_ostream &Dump(llvm::raw_ostream &) const; 74 75 private: 76 struct SourcePositionOrigin { 77 const std::string &path; 78 int line; 79 }; 80 81 void ReadFile(); 82 void IdentifyPayload(); 83 void RecordLineStarts(); 84 85 std::string path_; 86 std::unique_ptr<llvm::WritableMemoryBuffer> buf_; 87 std::vector<std::size_t> lineStart_; 88 std::size_t bom_end_{0}; 89 std::size_t buf_end_; 90 Encoding encoding_; 91 std::set<std::string> distinctPaths_; 92 std::map<std::size_t, SourcePositionOrigin> origins_; 93 }; 94 } // namespace Fortran::parser 95 #endif // FORTRAN_PARSER_SOURCE_H_ 96