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