fhicl-expand.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // fhicl-expand: read/write specified text, replacing each #include
4 // directive with the corresponding file's contents
5 //
6 // If called with no arguments, fhicl-expand reads from standard in.
7 // If called with one or more arguments, each argument is
8 // interepreted as the name of a file to be processed. If '-' (a
9 // single hyphen) is passed as a filename, this is interpreted as
10 // instruction to read from standard input.
11 //
12 // By default, the expanded inputs are all written to standard
13 // output, and any errors during processing are written to standard
14 // error. The -o (or --output) and -e (or --error) options can be
15 // used to send output to the named files.
16 // ======================================================================
17 
19 #include "cetlib/filepath_maker.h"
20 #include "cetlib/includer.h"
21 #include "cetlib/ostream_handle.h"
23 #include "cetlib_except/exception.h"
24 
25 #include <iostream>
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 namespace {
31 
32  std::string const fhicl_env_var{"FHICL_FILE_PATH"};
33 
34  // Error categories
35  std::string const help{"Help"};
36  std::string const processing{"Processing"};
37 
38  using std::string;
39  using strings = std::vector<string>;
40 
41  struct Options {
42  string error_filename;
43  string output_filename;
44  strings input_filenames;
45  std::unique_ptr<cet::filepath_maker> policy;
46  string lookup_path;
47  };
48 
49  Options process_arguments(int argc, char** argv);
50 
51  int do_including(std::string const& starting_filename,
52  cet::filepath_maker& lookup_policy,
53  std::ostream& to,
54  std::ostream& err);
55 }
56 
57 // ===================================================================
58 
59 int
60 main(int argc, char** argv)
61 {
62  Options opts;
63  try {
64  opts = process_arguments(argc, argv);
65  }
66  catch (cet::exception const& e) {
67  if (e.category() == help)
68  return 0;
69  if (e.category() == processing)
70  return 1;
71  }
72 
73  // Set output/error streams
74  auto out = cet::select_stream(opts.output_filename, std::cout);
75  auto err = cet::select_stream(opts.error_filename, std::cerr);
76 
77  int nfailures{};
78  for (std::string const& filename : opts.input_filenames)
79  nfailures += do_including(filename, *opts.policy, out, err);
80 
81  return nfailures;
82 }
83 
84 // ===================================================================
85 
86 namespace {
87 
88  Options
89  process_arguments(int argc, char** argv)
90  {
91  using namespace std;
92  namespace bpo = boost::program_options;
93 
94  // Parse the command line:
95 
96  bpo::options_description desc("fhicl-expand <options> [files]\nOptions");
97  Options opts;
98  // clang-format off
99  desc.add_options()
100  ("help,h", "produce help message")
101  ("inputs,i", bpo::value<strings>(&opts.input_filenames), "input files")
102  ("output,o", bpo::value<string>(&opts.output_filename), "output file")
103  ("error,e", bpo::value<string>(&opts.error_filename), "error file")
104  ("lookup-policy,l",
105  bpo::value<string>()->default_value("permissive"), "see --supported-policies")
106  ("path,p",
107  bpo::value<string>(&opts.lookup_path)->default_value(fhicl_env_var),
108  "path or environment variable to be used by lookup-policy")
109  ("supported-policies", "list the supported file lookup policies");
110  // clang-format on
111 
112  bpo::positional_options_description pd;
113  pd.add("inputs", -1);
114 
115  auto const vm = cet::parsed_program_options(argc, argv, desc, pd);
116 
117  // Interpret options:
118 
119  if (vm.count("help")) {
120  std::cout << desc << "\n";
121  throw cet::exception(help);
122  }
123 
124  cet::lookup_policy_selector const supported_policies{};
125  if (vm.count("supported-policies")) {
126  std::cout << supported_policies.help_message();
127  throw cet::exception(help);
128  }
129 
130  if (vm.count("lookup-policy") > 0) {
131  opts.policy = supported_policies.select(
132  vm["lookup-policy"].as<std::string>(), opts.lookup_path);
133  }
134 
135  if (opts.input_filenames.empty())
136  opts.input_filenames.push_back("-");
137 
138  return opts;
139  }
140 
141  int
142  do_including(std::string const& starting_filename,
143  cet::filepath_maker& lookup_policy,
144  std::ostream& to,
145  std::ostream& err) try {
146  cet::includer inc{starting_filename, lookup_policy};
147  cet::copy_all(inc, std::ostream_iterator<char>{to});
148  return 0;
149  }
150  catch (cet::exception const& e) {
151  err << "Error for file: " << starting_filename << '\n' << e.what() << '\n';
152  return 1;
153  }
154 }
ostream_handle select_stream(std::string const &filename, std::ostream &default_os)
boost::program_options::variables_map parsed_program_options(int argc, char **argv, boost::program_options::options_description const &desc, boost::program_options::positional_options_description const &pos={})
std::string string
Definition: nybbler.cc:12
STL namespace.
string filename
Definition: train.py:213
const double e
int main(int argc, char **argv)
Definition: fhicl-expand.cc:60
void err(const char *fmt,...)
Definition: message.cpp:226
auto copy_all(FwdCont &, FwdIter)
opts
Definition: ECLAPI.py:241
int do_including(std::string const &from, std::ostream &to)
Definition: inc-expand.cc:21
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::string help_message() const