souffle  2.0.2-371-g6315b36
SrcLocation.cpp
Go to the documentation of this file.
1 /*
2  * Souffle - A Datalog Compiler
3  * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved
4  * Licensed under the Universal Permissive License v 1.0 as shown at:
5  * - https://opensource.org/licenses/UPL
6  * - <souffle root>/licenses/SOUFFLE-UPL.txt
7  */
8 
9 /************************************************************************
10  *
11  * @file SrcLocation.cpp
12  *
13  * Structures to describe the location of AST nodes within input code.
14  *
15  ***********************************************************************/
16 
17 #include "parser/SrcLocation.h"
19 #include <cctype>
20 #include <cstdio>
21 #include <fstream>
22 #include <limits>
23 #include <sstream>
24 
25 namespace souffle {
26 
27 std::string getCurrentFilename(const std::vector<std::string>& filenames) {
28  if (filenames.empty()) {
29  return "";
30  }
31 
32  std::string path = ".";
33  for (std::string filename : filenames) {
34  if (!filename.empty() && filename[0] == '/') {
35  path = dirName(filename);
36  } else if (existFile(path + "/" + filename)) {
37  path = dirName(path + "/" + filename);
38  } else if (existFile(filename)) {
39  path = dirName(filename);
40  } else {
41  path = ".";
42  }
43  }
44 
45  return path + "/" + baseName(filenames.back());
46 }
47 
48 bool SrcLocation::operator<(const SrcLocation& other) const {
49  // Translate filename stack into current files
50  std::string filename = getCurrentFilename(filenames);
51  std::string otherFilename = getCurrentFilename(other.filenames);
52 
53  if (filename < otherFilename) {
54  return true;
55  }
56 
57  if (filename > otherFilename) {
58  return false;
59  }
60  if (start < other.start) {
61  return true;
62  }
63  if (start > other.start) {
64  return false;
65  }
66  if (end < other.end) {
67  return true;
68  }
69  return false;
70 }
71 
72 void SrcLocation::setFilename(std::string filename) {
73  if (filenames.empty()) {
74  filenames.emplace_back(filename);
75  return;
76  }
77  if (filenames.back() == filename) {
78  return;
79  }
80  if (filenames.size() > 1 && filenames.at(filenames.size() - 2) == filename) {
81  filenames.pop_back();
82  return;
83  }
84  filenames.emplace_back(filename);
85 }
86 
87 std::string SrcLocation::extloc() const {
88  std::string filename = getCurrentFilename(filenames);
89  std::ifstream in(filename);
90  std::stringstream s;
91  if (in.is_open()) {
92  s << "file " << baseName(filename) << " at line " << start.line << "\n";
93  for (int i = 0; i < start.line - 1; ++i) {
94  in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
95  }
96  int c;
97  int lineLen = 0;
98  int offsetColumn = start.column;
99  bool prevWhitespace = false;
100  bool afterFirstNonSpace = false;
101  while ((c = in.get()) != '\n' && c != EOF) {
102  s << (char)c;
103  lineLen++;
104 
105  // Offset column to account for C preprocessor having reduced
106  // consecutive non-leading whitespace chars to a single space.
107  if (std::isspace(c) != 0) {
108  if (afterFirstNonSpace && prevWhitespace && offsetColumn >= lineLen) {
109  offsetColumn++;
110  }
111  prevWhitespace = true;
112  } else {
113  prevWhitespace = false;
114  afterFirstNonSpace = true;
115  }
116  }
117  lineLen++; // Add new line
118  in.close();
119  s << "\n";
120  for (int i = 1; i <= lineLen; i++) {
121  char ch = (i == offsetColumn) ? '^' : '-';
122  s << ch;
123  }
124  in.close();
125  } else {
126  s << filename << ":" << start.line << ":" << start.column;
127  }
128  return s.str();
129 }
130 
131 void SrcLocation::print(std::ostream& out) const {
132  out << getCurrentFilename(filenames) << " [" << start << "-" << end << "]";
133 }
134 } // end of namespace souffle
souffle::baseName
std::string baseName(const std::string &filename)
Definition: FileUtil.h:199
souffle::existFile
bool existFile(const std::string &name)
Check whether a file exists in the file system.
Definition: FileUtil.h:71
souffle::SrcLocation::start
Point start
The start location.
Definition: SrcLocation.h:72
SrcLocation.h
souffle::dirName
std::string dirName(const std::string &name)
C++-style dirname.
Definition: FileUtil.h:132
souffle::SrcLocation::end
Point end
The End location.
Definition: SrcLocation.h:75
souffle::SrcLocation::operator<
bool operator<(const SrcLocation &other) const
A comparison for source locations.
Definition: SrcLocation.cpp:54
souffle::SrcLocation::Point::column
int column
The column in the source file.
Definition: SrcLocation.h:52
souffle::SrcLocation::filenames
std::vector< std::string > filenames
The file referred to.
Definition: SrcLocation.h:69
i
size_t i
Definition: json11.h:663
souffle::SrcLocation::print
void print(std::ostream &out) const
Definition: SrcLocation.cpp:137
souffle::SrcLocation::setFilename
void setFilename(std::string filename)
Definition: SrcLocation.cpp:78
souffle::SrcLocation::Point::line
int line
The line in the source file.
Definition: SrcLocation.h:49
souffle::getCurrentFilename
std::string getCurrentFilename(const std::vector< std::string > &filenames)
Definition: SrcLocation.cpp:33
FileUtil.h
souffle
Definition: AggregateOp.h:25
souffle::SrcLocation::extloc
std::string extloc() const
An extended string describing this location in a end-user friendly way.
Definition: SrcLocation.cpp:93