fhicl-dump.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // Executable for dumping processed configuration files
4 //
5 // ======================================================================
6 
10 #include "cetlib_except/demangle.h"
11 #include "fhiclcpp/ParameterSet.h"
13 
14 #include <iostream>
15 #include <memory>
16 #include <sstream>
17 #include <string>
18 #include <variant>
19 
20 using namespace fhicl;
21 using namespace fhicl::detail;
22 
23 using std::string;
24 
25 namespace {
26 
27  string const fhicl_env_var{"FHICL_FILE_PATH"};
28 
29  // Error categories
30  string const help{"Help"};
31  string const processing{"Processing"};
32  string const config{"Configuration"};
33 
34  struct Help {
36  };
37 
38  struct Options {
40  bool quiet{false};
41  string output_filename;
42  string input_filename;
43  std::unique_ptr<cet::filepath_maker> policy;
44  string lookup_path;
45  };
46 
47  std::variant<Options, Help> process_arguments(int argc, char** argv);
48 }
49 
50 //======================================================================
51 
52 int
53 main(int argc, char** argv)
54 {
55  auto const opts_or_help = process_arguments(argc, argv);
56  if (std::holds_alternative<Help>(opts_or_help)) {
57  std::cout << std::get<Help>(opts_or_help).msg;
58  return 0;
59  }
60 
61  auto const& opts = std::get<Options>(opts_or_help);
62  auto const pset =
63  fhicl::ParameterSet::make(opts.input_filename, *opts.policy);
64 
65  if (opts.quiet)
66  return 0;
67 
68  auto os = cet::select_stream(opts.output_filename, std::cout);
69 
70  os << "# Produced from '" << argv[0] << "' using:\n"
71  << "# Input : " << opts.input_filename << '\n'
72  << "# Policy : "
73  << cet::demangle_symbol(typeid(decltype(*opts.policy)).name()) << '\n'
74  << "# Path : \"" << opts.lookup_path << "\"\n\n"
75  << pset.to_indented_string(0, opts.mode);
76 }
77 
78 //======================================================================
79 
80 namespace {
81 
82  std::variant<Options, Help>
83  process_arguments(int argc, char** argv)
84  {
85  namespace bpo = boost::program_options;
86 
87  Options opts;
88 
89  bool annotate{false};
90  bool prefix_annotate{false};
91 
92  bpo::options_description desc("fhicl-dump [-c] <file>\nOptions");
93  // clang-format off
94  desc.add_options()
95  ("help,h", "produce this help message")
96  ("config,c", bpo::value<std::string>(&opts.input_filename), "input file")
97  ("output,o", bpo::value<std::string>(&opts.output_filename),
98  "output file (default is STDOUT)")
99  ("annotate,a",
100  bpo::bool_switch(&annotate),
101  "include source location annotations")
102  ("prefix-annotate",
103  bpo::bool_switch(&prefix_annotate),
104  "include source location annotations on line preceding parameter "
105  "assignment (mutually exclusive with 'annotate' option)")
106  ("quiet,q", "suppress output to STDOUT")
107  ("lookup-policy,l",
108  bpo::value<string>()->default_value("permissive"), "see --supported-policies")
109  ("path,p",
110  bpo::value<std::string>(&opts.lookup_path)->default_value(fhicl_env_var),
111  "path or environment variable to be used by lookup-policy")
112  ("supported-policies", "list the supported file lookup policies");
113  // clang-format on
114 
115  bpo::positional_options_description p;
116  p.add("config", -1);
117 
118  auto const vm = cet::parsed_program_options(argc, argv, desc, p);
119 
120  if (vm.count("help")) {
121  std::ostringstream os;
122  os << desc << '\n';
123  return Help{os.str()};
124  }
125 
126  cet::lookup_policy_selector const supported_policies{};
127  if (vm.count("supported-policies")) {
128  return Help{supported_policies.help_message()};
129  }
130 
131  if (vm.count("quiet")) {
132  if (annotate || prefix_annotate) {
133  throw cet::exception(config) << "Cannot specify both '--quiet' and "
134  "'--(prefix-)annotate' options.\n";
135  }
136  opts.quiet = true;
137  }
138 
139  if (annotate && prefix_annotate) {
140  throw cet::exception(config) << "Cannot specify both '--annotate' and "
141  "'--prefix-annotate' options.\n";
142  }
143 
144  if (vm.count("lookup-policy") > 0) {
145  opts.policy = supported_policies.select(
146  vm["lookup-policy"].as<std::string>(), opts.lookup_path);
147  }
148 
149  if (annotate)
150  opts.mode = print_mode::annotated;
151  if (prefix_annotate)
152  opts.mode = print_mode::prefix_annotated;
153 
154  if (!vm.count("config")) {
155  std::ostringstream err_stream;
156  err_stream << "\nMissing input configuration file.\n\n" << desc << '\n';
157  throw cet::exception(config) << err_stream.str();
158  }
159  return opts;
160  }
161 }
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={})
void msg(const char *fmt,...)
Definition: message.cpp:107
std::string string
Definition: nybbler.cc:12
static ParameterSet make(intermediate_table const &tbl)
Definition: ParameterSet.cc:68
int main(int argc, char **argv)
Definition: fhicl-dump.cc:53
static Config * config
Definition: config.cpp:1054
p
Definition: test.py:223
opts
Definition: ECLAPI.py:241
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::string help_message() const