LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
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 
18 #include "boost/program_options.hpp"
19 #include "cetlib/container_algorithms.h"
20 #include "cetlib_except/exception.h"
21 #include "cetlib/filepath_maker.h"
22 #include "cetlib/includer.h"
23 
24 #include <fstream>
25 #include <iostream>
26 #include <istream>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 namespace {
32 
33  std::string const fhicl_env_var{"FHICL_FILE_PATH"};
34 
35  // Error categories
36  std::string const help{"Help"};
37  std::string const processing{"Processing"};
38 
39  using std::string;
40  using strings = std::vector<string>;
41 
42  struct Options {
43  string error_filename;
44  string output_filename;
45  strings input_filenames;
46  int lookup_policy{};
47  string lookup_path;
48  };
49 
50  Options process_arguments(int argc, char* argv[]);
51 
52  std::unique_ptr<cet::filepath_maker> get_policy(
53  int const lookup_policy,
54  std::string const& lookup_path);
55 
56  int do_including(std::string const& starting_filename,
57  cet::filepath_maker& lookup_policy,
58  std::ostream& to,
59  std::ostream& err);
60 }
61 
62 // ===================================================================
63 
64 int
65 main(int argc, char* argv[])
66 {
67 
68  Options opts;
69  try {
70  opts = process_arguments(argc, argv);
71  }
72  catch (cet::exception const& e) {
73  if (e.category() == help)
74  return 0;
75  if (e.category() == processing)
76  return 1;
77  }
78 
79  // Set output/error streams
80  std::ofstream outfile(opts.output_filename.c_str());
81  std::ofstream errfile(opts.error_filename.c_str());
82 
83  std::ostream& out = opts.output_filename.empty() ? std::cout : outfile;
84  std::ostream& err = opts.error_filename.empty() ? std::cerr : errfile;
85 
86  auto const policy = get_policy(opts.lookup_policy, opts.lookup_path);
87 
88  int nfailures{};
89  for (std::string const& filename : opts.input_filenames)
90  nfailures += do_including(filename, *policy, out, err);
91 
92  return nfailures;
93 }
94 
95 // ===================================================================
96 
97 namespace {
98 
99  Options
100  process_arguments(int argc, char* argv[])
101  {
102  using namespace std;
103  namespace bpo = boost::program_options;
104 
105  // Parse the command line:
106 
107  bpo::options_description desc("fhicl-expand <options> [files]\nOptions");
108  Options opts;
109 
110  desc.add_options()("help,h", "produce help message")(
111  "inputs,i", bpo::value<strings>(&opts.input_filenames), "input files")(
112  "output,o", bpo::value<string>(&opts.output_filename), "output file")(
113  "error,e", bpo::value<string>(&opts.error_filename), "error file")(
114  "lookup-policy,l",
115  bpo::value<int>(&opts.lookup_policy)->default_value(1),
116  "lookup policy code:"
117  "\n 0 => cet::filepath_maker"
118  "\n 1 => cet::filepath_lookup"
119  "\n 2 => cet::filepath_lookup_nonabsolute"
120  "\n 3 => cet::filepath_lookup_after1")(
121  "path,p",
122  bpo::value<string>(&opts.lookup_path)->default_value(fhicl_env_var),
123  "path or environment variable to be used by lookup-policy");
124 
125  bpo::positional_options_description pd;
126  pd.add("inputs", -1);
127 
128  bpo::variables_map varmap;
129  try {
130  bpo::store(
131  bpo::command_line_parser(argc, argv).options(desc).positional(pd).run(),
132  varmap);
133  bpo::notify(varmap);
134  }
135  catch (bpo::error& err) {
136  std::ostringstream err_stream;
137  err_stream << "Error processing command line in " << argv[0] << ": "
138  << err.what() << '\n';
139  throw cet::exception(processing) << err_stream.str();
140  };
141 
142  // Interpret options:
143 
144  if (varmap.count("help")) {
145  std::cout << desc << "\n";
146  throw cet::exception(help);
147  }
148 
149  if (opts.input_filenames.empty())
150  opts.input_filenames.push_back("-");
151 
152  return opts;
153  }
154 
155  std::unique_ptr<cet::filepath_maker>
156  get_policy(int const lookup_policy, std::string const& lookup_path)
157  {
158  std::cerr << "Policy is " << lookup_policy << "; path is \"" << lookup_path
159  << "\"\n";
160  switch (lookup_policy) {
161  case 0:
162  return std::make_unique<cet::filepath_maker>();
163  case 1:
164  return std::make_unique<cet::filepath_lookup>(lookup_path);
165  case 2:
166  return std::make_unique<cet::filepath_lookup_nonabsolute>(lookup_path);
167  case 3:
168  return std::make_unique<cet::filepath_lookup_after1>(lookup_path);
169  default:
170  std::ostringstream err_stream;
171  err_stream << "Error: command line lookup-policy " << lookup_policy
172  << " is unknown; choose 0, 1, 2, or 3\n";
173  throw std::runtime_error(err_stream.str());
174  }
175  }
176 
177  int
178  do_including(std::string const& starting_filename,
179  cet::filepath_maker& lookup_policy,
180  std::ostream& to,
181  std::ostream& err) try {
182  cet::includer inc{starting_filename, lookup_policy};
183  cet::copy_all(inc, std::ostream_iterator<char>{to});
184  return 0;
185  }
186  catch (cet::exception const& e) {
187  err << "Error for file: " << starting_filename << '\n' << e.what() << '\n';
188  return 1;
189  }
190 }
STL namespace.
int main(int argc, char *argv[])
Definition: fhicl-expand.cc:65
Float_t e
Definition: plot.C:34
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33