include.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // include: File->string, interpolating #include'd files along the way
4 //
5 // ======================================================================
6 
7 #include "cetlib/include.h"
8 #include "cetlib/filesystem.h"
9 #include "cetlib/search_path.h"
10 #include "cetlib/split_by_regex.h"
11 #include "cetlib/trim.h"
12 #include "cetlib_except/coded_exception.h"
13 
14 #include <fstream>
15 #include <regex>
16 
17 // ----------------------------------------------------------------------
18 
19 namespace {
20  std::regex const reCarriageReturn{"\r"};
21  std::string const include_lit{"#include \""};
22  std::size_t const include_sz{include_lit.size()};
23 }
24 
25 namespace {
26  enum error { cant_open, cant_read, malformed };
27 
29  translate(error const code)
30  {
31  switch (code) {
32  case cant_open:
33  return "Can't locate or can't open specified file:";
34  case cant_read:
35  return "Can't read from supplied input stream:";
36  case malformed:
37  return "Malformed #include directive:";
38  default:
39  return "Unknown code";
40  }
41  }
42 
43  using include_exception = cet::coded_exception<error, translate>;
44 
45  std::vector<std::string>
46  getlines(std::istream& is)
47  {
48  std::vector<std::string> result;
49  for (std::string readline; std::getline(is, readline);) {
50  for (auto const& line : cet::split_by_regex(readline, reCarriageReturn)) {
51  result.emplace_back(line);
52  }
53  }
54  return result;
55  }
56 }
57 
58 using namespace cet::detail;
59 
60 // ----------------------------------------------------------------------
61 
62 void
63 cet::include(std::istream& in, std::string& result)
64 {
65  if (!in)
66  throw include_exception{cant_read};
67 
68  for (auto& line : getlines(in)) {
69  if (line.find(include_lit) != 0) { // ordinary line
70  result.append(line).append(1, '\n');
71  continue;
72  }
73  trim_right(line, "\t\r");
74  if (line.end()[-1] != '\"') // #include is missing trailing quote
75  throw include_exception{malformed} << line;
76 
77  std::string const fname{
78  line.substr(include_sz, line.size() - include_sz - 1)};
79  std::ifstream f{fname.c_str(), std::ios_base::in};
80  if (!f)
81  throw include_exception{cant_open} << fname;
82  include(f, result);
83  } // for
84 
85 } // include()
86 
87 // ----------------------------------------------------------------------
88 
89 void
90 cet::include(std::istream& in,
91  std::string const& search_path_arg,
93 {
94  cet::search_path const paths{search_path_arg};
95 
96  if (!in)
97  throw include_exception(cant_read);
98 
99  for (auto const& line : getlines(in)) {
100  if (line.find(include_lit) != 0) { // ordinary line
101  result.append(line).append(1, '\n');
102  continue;
103  }
104 
105  if (line.end()[-1] != '\"') // #include is missing its trailing quote
106  throw include_exception(malformed) << line;
107 
108  std::string const fname{
109  line.substr(include_sz, line.size() - include_sz - 1)};
110 
112  std::ifstream f{fname.c_str(), std::ios_base::in};
113  if (!f)
114  throw include_exception(cant_open) << fname;
115  include(f, search_path_arg, result);
116  } else {
117  std::ifstream f{paths.find_file(fname).c_str(), std::ios_base::in};
118  if (!f) {
119  throw include_exception(cant_open)
120  << fname << "\nusing path: " << paths;
121  }
122  include(f, search_path_arg, result);
123  }
124  } // for
125 
126 } // include()
127 
128 // ======================================================================
static QCString result
std::string string
Definition: nybbler.cc:12
std::string & trim_right(std::string &source, std::string const &t=" ")
Definition: trim.h:33
error
Definition: include.cc:26
std::vector< std::string > split_by_regex(std::string const &str, std::regex const &reDelimSet)
std::string translate(errors::ErrorCodes)
Definition: Exception.cc:18
bool is_absolute_filepath(std::string const &qualified_filename)
Definition: filesystem.cc:23
CodeOutputInterface * code
void include(std::istream &in, std::string &result)
Definition: include.cc:63
void line(double t, double *p, double &x, double &y, double &z)