xref: /llvm-project/flang/include/flang/Parser/source.h (revision f7a15e0021697e2346d3aa335dedf2bb3cf468f9)
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