openMSX
CommandLineParser.cc
Go to the documentation of this file.
1 #include "CommandLineParser.hh"
3 #include "Interpreter.hh"
4 #include "SettingsConfig.hh"
5 #include "File.hh"
6 #include "FileContext.hh"
7 #include "FileOperations.hh"
8 #include "GlobalCliComm.hh"
9 #include "StdioMessages.hh"
10 #include "Version.hh"
11 #include "CliConnection.hh"
12 #include "ConfigException.hh"
13 #include "FileException.hh"
14 #include "EnumSetting.hh"
15 #include "XMLException.hh"
16 #include "StringOp.hh"
17 #include "xrange.hh"
18 #include "GLUtil.hh"
19 #include "Reactor.hh"
20 #include "RomInfo.hh"
21 #include "hash_map.hh"
22 #include "one_of.hh"
23 #include "outer.hh"
24 #include "ranges.hh"
25 #include "stl.hh"
26 #include "view.hh"
27 #include "xxhash.hh"
28 #include "build-info.hh"
29 #include <cassert>
30 #include <iostream>
31 #include <memory>
32 
33 using std::cout;
34 using std::string;
35 using std::string_view;
36 using std::vector;
37 
38 namespace openmsx {
39 
40 // class CommandLineParser
41 
44 
46  : reactor(reactor_)
47  , msxRomCLI(*this)
48  , cliExtension(*this)
49  , replayCLI(*this)
50  , saveStateCLI(*this)
51  , cassettePlayerCLI(*this)
53  , laserdiscPlayerCLI(*this)
54 #endif
55  , diskImageCLI(*this)
56  , hdImageCLI(*this)
57  , cdImageCLI(*this)
58  , parseStatus(UNPARSED)
59 {
60  haveConfig = false;
61  haveSettings = false;
62 
63  registerOption("-h", helpOption, PHASE_BEFORE_INIT, 1);
64  registerOption("--help", helpOption, PHASE_BEFORE_INIT, 1);
65  registerOption("-v", versionOption, PHASE_BEFORE_INIT, 1);
66  registerOption("--version", versionOption, PHASE_BEFORE_INIT, 1);
67  registerOption("-bash", bashOption, PHASE_BEFORE_INIT, 1);
68 
69  registerOption("-setting", settingOption, PHASE_BEFORE_SETTINGS);
70  registerOption("-control", controlOption, PHASE_BEFORE_SETTINGS, 1);
71  registerOption("-script", scriptOption, PHASE_BEFORE_SETTINGS, 1); // correct phase?
72  registerOption("-command", commandOption, PHASE_BEFORE_SETTINGS, 1); // same phase as -script
73  registerOption("-testconfig", testConfigOption, PHASE_BEFORE_SETTINGS, 1);
74 
75  registerOption("-machine", machineOption, PHASE_LOAD_MACHINE);
76 
77  registerFileType({"tcl"}, scriptOption);
78 
79  // At this point all options and file-types must be registered
80  ranges::sort(options, CmpOptions());
81  ranges::sort(fileTypes, CmpFileTypes());
82 }
83 
85  const char* str, CLIOption& cliOption, ParsePhase phase, unsigned length)
86 {
87  options.emplace_back(str, OptionData{&cliOption, phase, length});
88 }
89 
91  std::initializer_list<string_view> extensions, CLIFileType& cliFileType)
92 {
93  append(fileTypes, view::transform(extensions,
94  [&](auto& ext) { return std::pair(ext, &cliFileType); }));
95 }
96 
97 bool CommandLineParser::parseOption(
98  const string& arg, span<string>& cmdLine, ParsePhase phase)
99 {
100  if (auto it = ranges::lower_bound(options, arg, CmpOptions());
101  (it != end(options)) && (it->first == arg)) {
102  // parse option
103  if (it->second.phase <= phase) {
104  try {
105  it->second.option->parseOption(arg, cmdLine);
106  return true;
107  } catch (MSXException& e) {
108  throw FatalError(std::move(e).getMessage());
109  }
110  }
111  }
112  return false; // unknown
113 }
114 
115 bool CommandLineParser::parseFileName(const string& arg, span<string>& cmdLine)
116 {
117  if (auto* handler = getFileTypeHandlerForFileName(arg)) {
118  try {
119  // parse filetype
120  handler->parseFileType(arg, cmdLine);
121  return true; // file processed
122  } catch (MSXException& e) {
123  throw FatalError(std::move(e).getMessage());
124  }
125  }
126  return false;
127 }
128 
129 CLIFileType* CommandLineParser::getFileTypeHandlerForFileName(string_view filename) const
130 {
131  auto inner = [&](string_view arg) -> CLIFileType* {
132  string_view extension = FileOperations::getExtension(arg); // includes leading '.' (if any)
133  if (extension.size() <= 1) {
134  return nullptr; // no extension -> no handler
135  }
136  extension.remove_prefix(1);
137 
138  auto it = ranges::lower_bound(fileTypes, extension, CmpFileTypes());
139  StringOp::casecmp cmp;
140  if ((it == end(fileTypes)) || !cmp(it->first, extension)) {
141  return nullptr; // unknown extension
142  }
143  return it->second;
144  };
145 
146  // First try the fileName as we get it from the commandline. This may
147  // be more interesting than the original fileName of a (g)zipped file:
148  // in case of an OMR file for instance, we want to select on the
149  // original extension, and not on the extension inside the gzipped
150  // file.
151  auto* result = inner(filename);
152  if (!result) {
153  try {
154  File file(userFileContext().resolve(filename));
155  result = inner(file.getOriginalName());
156  } catch (FileException&) {
157  // ignore
158  }
159  }
160  return result;
161 }
162 
163 void CommandLineParser::parse(int argc, char** argv)
164 {
165  parseStatus = RUN;
166 
167  auto cmdLineBuf = to_vector(view::transform(xrange(1, argc), [&](auto i) {
168  return FileOperations::getConventionalPath(argv[i]);
169  }));
170  span<string> cmdLine(cmdLineBuf);
171  vector<string> backupCmdLine;
172 
173  for (ParsePhase phase = PHASE_BEFORE_INIT;
174  (phase <= PHASE_LAST) && (parseStatus != EXIT);
175  phase = static_cast<ParsePhase>(phase + 1)) {
176  switch (phase) {
177  case PHASE_INIT:
178  reactor.init();
179  fileTypeCategoryInfo = std::make_unique<FileTypeCategoryInfoTopic>(
180  reactor.getOpenMSXInfoCommand(), *this);
181  getInterpreter().init(argv[0]);
182  break;
183  case PHASE_LOAD_SETTINGS:
184  // after -control and -setting has been parsed
185  if (parseStatus != CONTROL) {
186  // if there already is a XML-StdioConnection, we
187  // can't also show plain messages on stdout
188  auto& cliComm = reactor.getGlobalCliComm();
189  cliComm.addListener(std::make_unique<StdioMessages>());
190  }
191  if (!haveSettings) {
192  auto& settingsConfig =
194  // Load default settings file in case the user
195  // didn't specify one.
196  auto context = systemFileContext();
197  string filename = "settings.xml";
198  try {
199  settingsConfig.loadSetting(context, filename);
200  } catch (XMLException& e) {
201  reactor.getCliComm().printWarning(
202  "Loading of settings failed: ",
203  e.getMessage(), "\n"
204  "Reverting to default settings.");
205  } catch (FileException&) {
206  // settings.xml not found
207  } catch (ConfigException& e) {
208  throw FatalError("Error in default settings: ",
209  e.getMessage());
210  }
211  // Consider an attempt to load the settings good enough.
212  haveSettings = true;
213  // Even if parsing failed, use this file for saving,
214  // this forces overwriting a non-setting file.
215  settingsConfig.setSaveFilename(context, filename);
216  }
217  break;
218  case PHASE_DEFAULT_MACHINE: {
219  if (!haveConfig) {
220  // load default config file in case the user didn't specify one
221  const auto& machine =
222  reactor.getMachineSetting().getString();
223  try {
224  reactor.switchMachine(string(machine));
225  } catch (MSXException& e) {
226  reactor.getCliComm().printInfo(
227  "Failed to initialize default machine: ",
228  e.getMessage());
229  // Default machine is broken; fall back to C-BIOS config.
230  const auto& fallbackMachine =
231  reactor.getMachineSetting().getRestoreValue().getString();
232  reactor.getCliComm().printInfo(
233  "Using fallback machine: ", fallbackMachine);
234  try {
235  reactor.switchMachine(string(fallbackMachine));
236  } catch (MSXException& e2) {
237  // Fallback machine failed as well; we're out of options.
238  throw FatalError(std::move(e2).getMessage());
239  }
240  }
241  haveConfig = true;
242  }
243  break;
244  }
245  default:
246  // iterate over all arguments
247  while (!cmdLine.empty()) {
248  string arg = std::move(cmdLine.front());
249  cmdLine = cmdLine.subspan(1);
250  // first try options
251  if (!parseOption(arg, cmdLine, phase)) {
252  // next try the registered filetypes (xml)
253  if ((phase != PHASE_LAST) ||
254  !parseFileName(arg, cmdLine)) {
255  // no option or known file
256  backupCmdLine.push_back(arg);
257  if (auto it = ranges::lower_bound(options, arg, CmpOptions());
258  (it != end(options)) && (it->first == arg)) {
259  for (unsigned i = 0; i < it->second.length - 1; ++i) {
260  if (!cmdLine.empty()) {
261  backupCmdLine.push_back(std::move(cmdLine.front()));
262  cmdLine = cmdLine.subspan(1);
263  }
264  }
265  }
266  }
267  }
268  }
269  std::swap(backupCmdLine, cmdLineBuf);
270  backupCmdLine.clear();
271  cmdLine = cmdLineBuf;
272  break;
273  }
274  }
275  for (auto& opData : view::values(options)) {
276  opData.option->parseDone();
277  }
278  if (!cmdLine.empty() && (parseStatus != EXIT)) {
279  throw FatalError(
280  "Error parsing command line: ", cmdLine.front(), "\n"
281  "Use \"openmsx -h\" to see a list of available options");
282  }
283 }
284 
286 {
287  return parseStatus == one_of(CONTROL, TEST);
288 }
289 
291 {
292  assert(parseStatus != UNPARSED);
293  return parseStatus;
294 }
295 
297 {
298  return reactor.getMotherBoard();
299 }
300 
302 {
303  return reactor.getGlobalCommandController();
304 }
305 
307 {
308  return reactor.getInterpreter();
309 }
310 
311 
312 // Control option
313 
314 void CommandLineParser::ControlOption::parseOption(
315  const string& option, span<string>& cmdLine)
316 {
317  const auto& fullType = getArgument(option, cmdLine);
318  auto [type, arguments] = StringOp::splitOnFirst(fullType, ':');
319 
320  auto& parser = OUTER(CommandLineParser, controlOption);
321  auto& controller = parser.getGlobalCommandController();
322  auto& distributor = parser.reactor.getEventDistributor();
323  auto& cliComm = parser.reactor.getGlobalCliComm();
324  std::unique_ptr<CliListener> connection;
325  if (type == "stdio") {
326  connection = std::make_unique<StdioConnection>(
327  controller, distributor);
328 #ifdef _WIN32
329  } else if (type == "pipe") {
330  connection = std::make_unique<PipeConnection>(
331  controller, distributor, arguments);
332 #endif
333  } else {
334  throw FatalError("Unknown control type: '", type, '\'');
335  }
336  cliComm.addListener(std::move(connection));
337 
338  parser.parseStatus = CommandLineParser::CONTROL;
339 }
340 
341 string_view CommandLineParser::ControlOption::optionHelp() const
342 {
343  return "Enable external control of openMSX process";
344 }
345 
346 
347 // Script option
348 
349 void CommandLineParser::ScriptOption::parseOption(
350  const string& option, span<string>& cmdLine)
351 {
352  parseFileType(getArgument(option, cmdLine), cmdLine);
353 }
354 
355 string_view CommandLineParser::ScriptOption::optionHelp() const
356 {
357  return "Run extra startup script";
358 }
359 
360 void CommandLineParser::ScriptOption::parseFileType(
361  const string& filename, span<std::string>& /*cmdLine*/)
362 {
363  scripts.push_back(filename);
364 }
365 
366 string_view CommandLineParser::ScriptOption::fileTypeHelp() const
367 {
368  return "Extra Tcl script to run at startup";
369 }
370 
371 string_view CommandLineParser::ScriptOption::fileTypeCategoryName() const
372 {
373  return "script";
374 }
375 
376 
377 // Command option
378 void CommandLineParser::CommandOption::parseOption(
379  const std::string& option, span<std::string>& cmdLine)
380 {
381  commands.push_back(getArgument(option, cmdLine));
382 }
383 
384 std::string_view CommandLineParser::CommandOption::optionHelp() const
385 {
386  return "Run Tcl command at startup (see also -script)";
387 }
388 
389 
390 // Help option
391 
392 static string formatSet(const vector<string_view>& inputSet, string::size_type columns)
393 {
394  string outString;
395  string::size_type totalLength = 0; // ignore the starting spaces for now
396  for (auto& temp : inputSet) {
397  if (totalLength == 0) {
398  // first element ?
399  strAppend(outString, " ", temp);
400  totalLength = temp.size();
401  } else {
402  outString += ", ";
403  if ((totalLength + temp.size()) > columns) {
404  strAppend(outString, "\n ", temp);
405  totalLength = temp.size();
406  } else {
407  strAppend(outString, temp);
408  totalLength += 2 + temp.size();
409  }
410  }
411  }
412  if (totalLength < columns) {
413  outString.append(columns - totalLength, ' ');
414  }
415  return outString;
416 }
417 
418 static string formatHelptext(string_view helpText,
419  unsigned maxLength, unsigned indent)
420 {
421  string outText;
422  string_view::size_type index = 0;
423  while (helpText.substr(index).size() > maxLength) {
424  auto pos = helpText.substr(index, maxLength).rfind(' ');
425  if (pos == string_view::npos) {
426  pos = helpText.substr(maxLength).find(' ');
427  if (pos == string_view::npos) {
428  pos = helpText.substr(index).size();
429  }
430  }
431  strAppend(outText, helpText.substr(index, index + pos), '\n',
432  string(indent, ' '));
433  index = pos + 1;
434  }
435  strAppend(outText, helpText.substr(index));
436  return outText;
437 }
438 
439 // items grouped per common help-text
441 static void printItemMap(const GroupedItems& itemMap)
442 {
443  auto printSet = to_vector(view::transform(itemMap, [](auto& p) {
444  return strCat(formatSet(p.second, 15), ' ',
445  formatHelptext(p.first, 50, 20));
446  }));
447  ranges::sort(printSet);
448  for (auto& s : printSet) {
449  cout << s << '\n';
450  }
451 }
452 
453 
454 // class HelpOption
455 
456 void CommandLineParser::HelpOption::parseOption(
457  const string& /*option*/, span<string>& /*cmdLine*/)
458 {
459  auto& parser = OUTER(CommandLineParser, helpOption);
460  const auto& fullVersion = Version::full();
461  cout << fullVersion << '\n'
462  << string(fullVersion.size(), '=') << "\n"
463  "\n"
464  "usage: openmsx [arguments]\n"
465  " an argument is either an option or a filename\n"
466  "\n"
467  " this is the list of supported options:\n";
468 
469  GroupedItems itemMap;
470  for (const auto& [name, data] : parser.options) {
471  const auto& helpText = data.option->optionHelp();
472  if (!helpText.empty()) {
473  itemMap[helpText].push_back(name);
474  }
475  }
476  printItemMap(itemMap);
477 
478  cout << "\n"
479  " this is the list of supported file types:\n";
480 
481  itemMap.clear();
482  for (const auto& [ext, data] : parser.fileTypes) {
483  itemMap[data->fileTypeHelp()].push_back(ext);
484  }
485  printItemMap(itemMap);
486 
487  parser.parseStatus = CommandLineParser::EXIT;
488 }
489 
490 string_view CommandLineParser::HelpOption::optionHelp() const
491 {
492  return "Shows this text";
493 }
494 
495 
496 // class VersionOption
497 
498 void CommandLineParser::VersionOption::parseOption(
499  const string& /*option*/, span<string>& /*cmdLine*/)
500 {
501  cout << Version::full() << "\n"
502  "flavour: " << BUILD_FLAVOUR << "\n"
503  "components: " << BUILD_COMPONENTS << '\n';
504  auto& parser = OUTER(CommandLineParser, versionOption);
505  parser.parseStatus = CommandLineParser::EXIT;
506 }
507 
508 string_view CommandLineParser::VersionOption::optionHelp() const
509 {
510  return "Prints openMSX version and exits";
511 }
512 
513 
514 // Machine option
515 
516 void CommandLineParser::MachineOption::parseOption(
517  const string& option, span<string>& cmdLine)
518 {
519  auto& parser = OUTER(CommandLineParser, machineOption);
520  if (parser.haveConfig) {
521  throw FatalError("Only one machine option allowed");
522  }
523  try {
524  parser.reactor.switchMachine(getArgument(option, cmdLine));
525  } catch (MSXException& e) {
526  throw FatalError(std::move(e).getMessage());
527  }
528  parser.haveConfig = true;
529 }
530 
531 string_view CommandLineParser::MachineOption::optionHelp() const
532 {
533  return "Use machine specified in argument";
534 }
535 
536 
537 // class SettingOption
538 
539 void CommandLineParser::SettingOption::parseOption(
540  const string& option, span<string>& cmdLine)
541 {
542  auto& parser = OUTER(CommandLineParser, settingOption);
543  if (parser.haveSettings) {
544  throw FatalError("Only one setting option allowed");
545  }
546  try {
547  auto& settingsConfig = parser.reactor.getGlobalCommandController().getSettingsConfig();
548  settingsConfig.loadSetting(
549  currentDirFileContext(), getArgument(option, cmdLine));
550  parser.haveSettings = true;
551  } catch (FileException& e) {
552  throw FatalError(std::move(e).getMessage());
553  } catch (ConfigException& e) {
554  throw FatalError(std::move(e).getMessage());
555  }
556 }
557 
558 string_view CommandLineParser::SettingOption::optionHelp() const
559 {
560  return "Load an alternative settings file";
561 }
562 
563 
564 // class TestConfigOption
565 
566 void CommandLineParser::TestConfigOption::parseOption(
567  const string& /*option*/, span<string>& /*cmdLine*/)
568 {
569  auto& parser = OUTER(CommandLineParser, testConfigOption);
570  parser.parseStatus = CommandLineParser::TEST;
571 }
572 
573 string_view CommandLineParser::TestConfigOption::optionHelp() const
574 {
575  return "Test if the specified config works and exit";
576 }
577 
578 // class BashOption
579 
580 void CommandLineParser::BashOption::parseOption(
581  const string& /*option*/, span<string>& cmdLine)
582 {
583  auto& parser = OUTER(CommandLineParser, bashOption);
584  string_view last = cmdLine.empty() ? string_view{} : cmdLine.front();
585  cmdLine = cmdLine.subspan(0, 0); // eat all remaining parameters
586 
587  if (last == "-machine") {
588  for (auto& s : Reactor::getHwConfigs("machines")) {
589  cout << s << '\n';
590  }
591  } else if (StringOp::startsWith(last, "-ext")) {
592  for (auto& s : Reactor::getHwConfigs("extensions")) {
593  cout << s << '\n';
594  }
595  } else if (last == "-romtype") {
596  for (auto& s : RomInfo::getAllRomTypes()) {
597  cout << s << '\n';
598  }
599  } else {
600  for (const auto& name : view::keys(parser.options)) {
601  cout << name << '\n';
602  }
603  }
604  parser.parseStatus = CommandLineParser::EXIT;
605 }
606 
607 string_view CommandLineParser::BashOption::optionHelp() const
608 {
609  return {}; // don't include this option in --help
610 }
611 
612 // class FileTypeCategoryInfoTopic
613 
614 CommandLineParser::FileTypeCategoryInfoTopic::FileTypeCategoryInfoTopic(
615  InfoCommand& openMSXInfoCommand, const CommandLineParser& parser_)
616  : InfoTopic(openMSXInfoCommand, "file_type_category")
617  , parser(parser_)
618 {
619 }
620 
621 void CommandLineParser::FileTypeCategoryInfoTopic::execute(
622  span<const TclObject> tokens, TclObject& result) const
623 {
624  checkNumArgs(tokens, 3, "filename");
625  assert(tokens.size() == 3);
626 
627  // get the category and add it to result
628  std::string_view fileName = tokens[2].getString();
629  if (const auto* handler = parser.getFileTypeHandlerForFileName(fileName)) {
630  result.addListElement(handler->fileTypeCategoryName());
631  } else {
632  result.addListElement("unknown");
633  }
634 }
635 
636 string CommandLineParser::FileTypeCategoryInfoTopic::help(const std::vector<std::string>& /*tokens*/) const
637 {
638  return "Returns the file type category for the given file.";
639 }
640 
641 } // namespace openmsx
openmsx::CommandLineParser::PHASE_LOAD_MACHINE
@ PHASE_LOAD_MACHINE
Definition: CommandLineParser.hh:44
openmsx::XMLException
Definition: XMLException.hh:9
one_of.hh
ConfigException.hh
FileException.hh
openmsx::CLIOption
Definition: CLIOption.hh:10
span::empty
constexpr bool empty() const noexcept
Definition: span.hh:300
xrange
auto xrange(T e)
Definition: xrange.hh:170
StringOp::startsWith
bool startsWith(string_view total, string_view part)
Definition: StringOp.cc:71
xxhash.hh
openmsx::RomInfo::getAllRomTypes
static std::vector< std::string_view > getAllRomTypes()
Definition: RomInfo.cc:190
ranges::sort
void sort(RandomAccessRange &&range)
Definition: ranges.hh:35
openmsx::Reactor::getOpenMSXInfoCommand
InfoCommand & getOpenMSXInfoCommand()
Definition: Reactor.cc:321
openmsx::CommandLineParser::registerOption
void registerOption(const char *str, CLIOption &cliOption, ParsePhase phase=PHASE_LAST, unsigned length=2)
Definition: CommandLineParser.cc:84
XMLException.hh
openmsx::ConfigException
Definition: ConfigException.hh:9
openmsx::CommandLineParser::getInterpreter
Interpreter & getInterpreter() const
Definition: CommandLineParser.cc:306
openmsx::CommandLineParser::getMotherBoard
MSXMotherBoard * getMotherBoard() const
Definition: CommandLineParser.cc:296
CommandLineParser.hh
openmsx::CommandLineParser::ParsePhase
ParsePhase
Definition: CommandLineParser.hh:38
ranges::lower_bound
auto lower_bound(ForwardRange &&range, const T &value)
Definition: ranges.hh:71
gl::length
T length(const vecN< N, T > &x)
Definition: gl_vec.hh:348
openmsx::CLIFileType
Definition: CLIOption.hh:25
StringOp::splitOnFirst
std::pair< string_view, string_view > splitOnFirst(string_view str, string_view chars)
Definition: StringOp.cc:153
XXHasher
Definition: xxhash.hh:153
openmsx::CommandLineParser::isHiddenStartup
bool isHiddenStartup() const
Need to suppress renderer window on startup?
Definition: CommandLineParser.cc:285
StringOp::casecmp
Definition: StringOp.hh:68
ranges.hh
StdioMessages.hh
openmsx::MSXException
Definition: MSXException.hh:10
Interpreter.hh
GlobalCliComm.hh
openmsx::CommandLineParser::parse
void parse(int argc, char **argv)
Definition: CommandLineParser.cc:163
openmsx::userFileContext
FileContext userFileContext(string_view savePath)
Definition: FileContext.cc:164
openmsx::CommandLineParser::PHASE_LOAD_SETTINGS
@ PHASE_LOAD_SETTINGS
Definition: CommandLineParser.hh:42
strAppend
void strAppend(std::string &result, Ts &&...ts)
Definition: strCat.hh:644
openmsx::CliComm::printInfo
void printInfo(std::string_view message)
Definition: CliComm.cc:5
openmsx::CommandLineParser::PHASE_BEFORE_SETTINGS
@ PHASE_BEFORE_SETTINGS
Definition: CommandLineParser.hh:41
span::subspan
constexpr subspan_return_t< Offset, Count > subspan() const
Definition: span.hh:266
COMPONENT_LASERDISC
#define COMPONENT_LASERDISC
Definition: components.hh:8
openmsx::CommandLineParser::PHASE_DEFAULT_MACHINE
@ PHASE_DEFAULT_MACHINE
Definition: CommandLineParser.hh:45
span::front
constexpr reference front() const
Definition: span.hh:310
Version.hh
span
Definition: span.hh:126
openmsx::Reactor
Contains the main loop of openMSX.
Definition: Reactor.hh:67
Reactor.hh
OUTER
#define OUTER(type, member)
Definition: outer.hh:41
openmsx::CommandLineParser::PHASE_INIT
@ PHASE_INIT
Definition: CommandLineParser.hh:40
view::transform
auto transform(Range &&range, UnaryOp op)
Definition: view.hh:306
openmsx::CliComm::printWarning
void printWarning(std::string_view message)
Definition: CliComm.cc:10
openmsx::CommandLineParser::TEST
@ TEST
Definition: CommandLineParser.hh:37
openmsx::Reactor::getMotherBoard
MSXMotherBoard * getMotherBoard() const
Definition: Reactor.cc:366
openmsx::currentDirFileContext
FileContext currentDirFileContext()
Definition: FileContext.cc:180
SettingsConfig.hh
File.hh
openmsx::Reactor::getInterpreter
Interpreter & getInterpreter()
Definition: Reactor.cc:311
openmsx::MSXMotherBoard
Definition: MSXMotherBoard.hh:61
openmsx::CommandLineParser::RUN
@ RUN
Definition: CommandLineParser.hh:37
one_of
Definition: one_of.hh:7
openmsx::filename
constexpr const char *const filename
Definition: FirmwareSwitch.cc:10
view::values
auto values(Map &&map)
Definition: view.hh:317
view::keys
auto keys(Map &&map)
Definition: view.hh:311
openmsx::FileException
Definition: FileException.hh:9
openmsx::Interpreter::init
void init(const char *programName)
Definition: Interpreter.cc:68
build-info.hh
openmsx::CommandLineParser::UNPARSED
@ UNPARSED
Definition: CommandLineParser.hh:37
view.hh
EnumSetting.hh
openmsx::CmpFileTypes
CmpTupleElement< 0, StringOp::caseless > CmpFileTypes
Definition: CommandLineParser.cc:43
openmsx::CommandLineParser::CommandLineParser
CommandLineParser(Reactor &reactor)
Definition: CommandLineParser.cc:45
FileContext.hh
openmsx::FatalError
Definition: MSXException.hh:31
openmsx::maxLength
constexpr unsigned maxLength
Definition: V9990CmdEngine.cc:19
hash_map.hh
FileOperations.hh
outer.hh
openmsx::CommandLineParser
Definition: CommandLineParser.hh:35
openmsx::CommandLineParser::ParseStatus
ParseStatus
Definition: CommandLineParser.hh:37
CmpTupleElement
Definition: stl.hh:29
openmsx::Reactor::switchMachine
void switchMachine(const std::string &machine)
Definition: Reactor.cc:422
openmsx::Reactor::getGlobalCliComm
GlobalCliComm & getGlobalCliComm()
Definition: Reactor.hh:82
span::size
constexpr index_type size() const noexcept
Definition: span.hh:296
gl::context
std::unique_ptr< Context > context
Definition: GLContext.cc:9
RomInfo.hh
StringOp.hh
openmsx::Reactor::getCliComm
CliComm & getCliComm()
Definition: Reactor.cc:306
openmsx::GroupedItems
hash_map< string_view, vector< string_view >, XXHasher > GroupedItems
Definition: CommandLineParser.cc:440
openmsx::FileOperations::getConventionalPath
const std::string & getConventionalPath(const std::string &path)
Returns the path in conventional path-delimiter.
Definition: FileOperations.hh:148
openmsx::EnumSetting::getString
std::string_view getString() const
Definition: EnumSetting.hh:109
GlobalCommandController.hh
detail::append
void append(Result &)
Definition: stl.hh:340
openmsx::Version::full
static std::string full()
Definition: Version.cc:8
stl.hh
openmsx::Reactor::getHwConfigs
static std::vector< std::string > getHwConfigs(std::string_view type)
Definition: Reactor.cc:326
openmsx::CommandLineParser::EXIT
@ EXIT
Definition: CommandLineParser.hh:37
GLUtil.hh
openmsx::CommandLineParser::getParseStatus
ParseStatus getParseStatus() const
Definition: CommandLineParser.cc:290
CliConnection.hh
openmsx::Reactor::getMachineSetting
EnumSetting< int > & getMachineSetting()
Definition: Reactor.hh:89
openmsx::CommandLineParser::getGlobalCommandController
GlobalCommandController & getGlobalCommandController() const
Definition: CommandLineParser.cc:301
openmsx::CmpOptions
LessTupleElement< 0 > CmpOptions
Definition: CommandLineParser.cc:42
openmsx::CommandLineParser::PHASE_BEFORE_INIT
@ PHASE_BEFORE_INIT
Definition: CommandLineParser.hh:39
openmsx::FileOperations::getExtension
string_view getExtension(string_view path)
Returns the extension portion of a path.
Definition: FileOperations.cc:406
openmsx::MSXException::getMessage
const std::string & getMessage() const &
Definition: MSXException.hh:23
openmsx::CommandLineParser::registerFileType
void registerFileType(std::initializer_list< std::string_view > extensions, CLIFileType &cliFileType)
Definition: CommandLineParser.cc:90
openmsx::CommandLineParser::PHASE_LAST
@ PHASE_LAST
Definition: CommandLineParser.hh:46
strCat
std::string strCat(Ts &&...ts)
Definition: strCat.hh:573
openmsx::Interpreter
Definition: Interpreter.hh:17
openmsx::GlobalCommandController
Definition: GlobalCommandController.hh:37
openmsx::Reactor::getGlobalCommandController
GlobalCommandController & getGlobalCommandController()
Definition: Reactor.hh:83
openmsx::CommandLineParser::CONTROL
@ CONTROL
Definition: CommandLineParser.hh:37
openmsx
This file implemented 3 utility functions:
Definition: Autofire.cc:5
to_vector
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))>>
Definition: stl.hh:316
xrange.hh
openmsx::Reactor::init
void init()
Definition: Reactor.cc:212
openmsx::GlobalCliComm::addListener
void addListener(std::unique_ptr< CliListener > listener)
Definition: GlobalCliComm.cc:19
hash_map
Definition: hash_map.hh:32
openmsx::GlobalCommandController::getSettingsConfig
SettingsConfig & getSettingsConfig()
Definition: GlobalCommandController.hh:88
openmsx::systemFileContext
FileContext systemFileContext()
Definition: FileContext.cc:152