souffle  2.0.2-371-g6315b36
Public Member Functions | Private Attributes
souffle::MainConfig Class Reference

#include <Global.h>

Inheritance diagram for souffle::MainConfig:
Inheritance graph
Collaboration diagram for souffle::MainConfig:
Collaboration graph

Public Member Functions

const std::string & help () const
 
 MainConfig ()
 
void processArgs (int argc, char **argv, const std::string &header, const std::string &footer, const std::vector< MainOption > mainOptions)
 

Private Attributes

std::string _help
 

Detailed Description

Definition at line 113 of file Global.h.

Constructor & Destructor Documentation

◆ MainConfig()

souffle::MainConfig::MainConfig ( )
inline

Definition at line 116 of file Global.h.

References _help.

Member Function Documentation

◆ help()

const std::string& souffle::MainConfig::help ( ) const
inline

Definition at line 123 of file Global.h.

128  {

Referenced by souffle::main().

◆ processArgs()

void souffle::MainConfig::processArgs ( int  argc,
char **  argv,
const std::string &  header,
const std::string &  footer,
const std::vector< MainOption mainOptions 
)

Definition at line 35 of file Global.cpp.

36  {
37  // create a stream to be 'printed' to
38  std::stringstream ss;
39 
40  // print the header
41  ss << header;
42 
43  // compute the maximum length of a line of the help text without including the description
44  std::size_t maxLineLengthWithoutDescription = 0;
45  {
46  // initially compute the maximum line length without the long option, arguments, or description
47  std::stringstream lineSchema;
48  const auto shortOption = "?";
49  const auto longOption = "";
50  const auto arguments = "";
51  const auto description = "";
52  lineSchema << TWO_SPACES << "-" << shortOption << "," << ONE_SPACE << "--" << longOption << "=<"
53  << arguments << ">" << TWO_SPACES << description;
54  maxLineLengthWithoutDescription = lineSchema.str().size();
55  }
56  {
57  // then compute the maximum length of the long option plus the description
58  std::size_t maxLongOptionPlusArgumentLength = 0;
59  for (const MainOption& opt : mainOptions) {
60  if (opt.longName.empty()) {
61  continue;
62  }
63  const auto longOptionPlusArgumentLength = opt.longName.size() + opt.argument.size();
64  if (longOptionPlusArgumentLength > maxLongOptionPlusArgumentLength) {
65  maxLongOptionPlusArgumentLength = longOptionPlusArgumentLength;
66  }
67  }
68  maxLineLengthWithoutDescription += maxLongOptionPlusArgumentLength;
69  }
70 
71  // iterate over the options and pretty print them, using the computed maximum line length without the
72  // description
73  for (const MainOption& opt : mainOptions) {
74  // the current line
75  std::stringstream line;
76 
77  // if it is the main option, do nothing
78  if (opt.longName.empty()) {
79  continue;
80  }
81 
82  // print the short form name and the argument parameter
83  line << TWO_SPACES;
84  if (isalpha(opt.shortName) != 0) {
85  line << "-" << opt.shortName << ",";
86  } else {
87  line << THREE_SPACES;
88  }
89 
90  // print the long form name
91  line << ONE_SPACE << "--" << opt.longName;
92 
93  // print the argument parameter
94  if (!opt.argument.empty()) {
95  line << "=<" << opt.argument << ">";
96  }
97 
98  // again, pad with empty space for prettiness
99  for (std::size_t lineLength = line.str().size(); lineLength < maxLineLengthWithoutDescription;
100  ++lineLength) {
101  line << ONE_SPACE;
102  }
103 
104  // print the description
105  line << opt.description << std::endl;
106 
107  ss << line.str();
108  }
109 
110  // print the footer
111  ss << footer;
112 
113  // finally, store the help text as a string
114  _help = ss.str();
115  }
116 
117  // use the main options to define the global configuration
118  {
119  // array of long names for classic getopt processing
120  option longNames[mainOptions.size()];
121  // string of short names for classic getopt processing
122  std::string shortNames = "";
123  // table to map the short name to its option
124  std::map<const char, const MainOption*> optionTable;
125  // counter to be incremented at each loop
126  int i = 0;
127  // iterate over the options provided
128  for (const MainOption& opt : mainOptions) {
129  assert(opt.shortName != '?' && "short name for option cannot be '?'");
130  // put the option in the table, referenced by its short name
131  optionTable[opt.shortName] = &opt;
132  // set the default value for the option, if it exists
133  if (!opt.byDefault.empty()) {
134  set(opt.longName, opt.byDefault);
135  }
136  // skip the next bit if it is the option for the datalog file
137  if (opt.longName.empty()) {
138  continue;
139  }
140  // convert the main option to a plain old getopt option and put it in the array
141  longNames[i] = {opt.longName.c_str(), opt.argument.empty() ? 0 : 1, nullptr, opt.shortName};
142  // append the short name of the option to the string of short names
143  shortNames += opt.shortName;
144  // indicating with a ':' if it takes an argument
145  if (!opt.argument.empty()) {
146  shortNames += ":";
147  }
148  // increment counter
149  ++i;
150  }
151  // the terminal option, needs to be null
152  longNames[i] = {nullptr, 0, nullptr, 0};
153 
154  // use getopt to process the arguments given to the command line, with the parameters being the
155  // short and long names from above
156  int c;
157  while ((c = getopt_long(argc, argv, shortNames.c_str(), longNames, nullptr)) != EOF) {
158  // case for the unknown option
159  if (c == '?') {
160  std::cerr << Global::config().help();
161  throw std::runtime_error("Error: Unknown command line option.");
162  }
163  // obtain an iterator to the option in the table referenced by the current short name
164  auto iter = optionTable.find(c);
165  // case for the unknown option, again
166  assert(iter != optionTable.end() && "unexpected case in getopt");
167  // define the value for the option in the global configuration as its argument or an empty string
168  // if no argument exists
169  std::string arg = optarg != nullptr ? std::string(optarg) : std::string();
170  // if the option allows multiple arguments
171  if (iter->second->takesMany) {
172  // set the value of the option in the global config to the concatenation of its previous
173  // value, a space and the current argument
174  set(iter->second->longName, get(iter->second->longName) + ' ' + arg);
175  // otherwise, set the value of the option in the global config
176  } else {
177  // but only if it isn't set already
178  if (has(iter->second->longName) &&
179  (iter->second->byDefault.empty() ||
180  !has(iter->second->longName, iter->second->byDefault))) {
181  throw std::runtime_error(
182  "Error: Only one argument allowed for option '" + iter->second->longName + "'");
183  }
184  set(iter->second->longName, arg);
185  }
186  }
187  }
188 
189  // obtain the name of the datalog file, and store it in the option with the empty key
190  if (argc > 1 && !Global::config().has("help") && !Global::config().has("version")) {
191  std::string filename = "";
192  // ensure that the optind is less than the total number of arguments
193  if (argc > 1 && optind >= argc) {
194  std::cerr << Global::config().help();
195  throw std::runtime_error("Error: Unknown command line option.");
196  }
197  // if only one datalog program is allowed
198  if (mainOptions[0].longName.empty() && mainOptions[0].takesMany) {
199  // set the option in the global config for the main datalog file to that specified by the command
200  // line arguments
201  set("", std::string(argv[optind]));
202  // otherwise, if multiple input filenames are allowed
203  } else {
204  std::string filenames = "";
205  // for each of the command line arguments not associated with an option
206  for (; optind < argc; optind++) {
207  // append this filename to the concatenated string of filenames
208  if (filenames.empty()) {
209  filenames = argv[optind];
210  } else {
211  filenames = filenames + " " + std::string(argv[optind]);
212  }
213  }
214  // set the option in the global config for the main datalog file to all those specified by the
215  // command line arguments
216  set("", filenames);
217  }
218  }
219 }
220 } // namespace souffle

References _help, and souffle::profile::ss.

Referenced by souffle::main().

Field Documentation

◆ _help

std::string souffle::MainConfig::_help
private

Definition at line 129 of file Global.h.

Referenced by MainConfig(), and processArgs().


The documentation for this class was generated from the following files:
souffle::BaseTable< std::string, std::string >::has
bool has(const std::string &key) const
Definition: Global.h:71
souffle::MainConfig::help
const std::string & help() const
Definition: Global.h:123
souffle::BaseTable< std::string, std::string >::get
const std::string & get(const std::string &key) const
Definition: Global.h:63
souffle::MainConfig::_help
std::string _help
Definition: Global.h:129
i
size_t i
Definition: json11.h:663
souffle::Global::config
static MainConfig & config()
Definition: Global.h:141
std
Definition: Brie.h:3053
souffle::BaseTable< std::string, std::string >::set
void set(const std::string &key)
Definition: Global.h:80
souffle::profile::ss
class souffle::profile::Tui ss
Definition: Tui.h:336