ArgList::iterator Engine::parse(ArgList& list, ArgList::iterator begin) { rebuild(); bool foundNonSwitches = false; ArgList::iterator firstNonSwitch; while (begin != list.end()) { // Parse a row of switches begin = parseConsecutiveSwitches(list, begin); // End of switches? if (begin == list.end()) break; // If the end is the "--" marker, take it out of the list as well if (*begin == "--") { list.eraseAndAdvance(begin); break; } if (!foundNonSwitches) { // Mark the start of non-switches if we haven't done it already firstNonSwitch = begin; foundNonSwitches = true; } // Skip past the non switches while (begin != list.end() && !list.isSwitch(begin)) ++begin; } return foundNonSwitches ? firstNonSwitch : begin; }
ArgList::iterator Engine::parseKnownSwitches(ArgList& list, ArgList::iterator begin) { // Parse the first items, chopping them off the list, until it works while (1) { if (begin == list.end()) return begin; if (!list.isSwitch(begin)) break; pair<ArgList::iterator, bool> res = parseFirstIfKnown(list, begin); if (!res.second) break; begin = res.first; } // If requested, stop here if (no_switches_after_first_arg) return begin; // Parse the next items, chopping off the list only those that we know for (ArgList::iterator cur = begin; cur != list.end(); ) { // Skip non-switches if (!list.isSwitch(cur)) { ++cur; continue; } pair<ArgList::iterator, bool> res = parseFirstIfKnown(list, cur); if (!res.second) // If the switch is not handled, move past it ++cur; else cur = res.first; } return begin; }
ArgList::iterator OptionEngine::parseConsecutiveSwitches(ArgList& list, ArgList::iterator begin) { while (begin != list.end() && list.isSwitch(*begin)) { pair<ArgList::iterator, bool> res = parseFirstIfKnown(list, begin); if (!res.second) { if ((*begin)[1] != '-') throw exception::BadOption(string("unknown short option ") + *begin); else throw exception::BadOption(string("unknown long option ") + *begin); } begin = res.first; } return begin; }
ArgList::iterator Engine::parse(ArgList& list, ArgList::iterator begin) { rebuild(); // Parse and remove known switches begin = parseKnownSwitches(list, begin); m_found_command = 0; // Check if we have to handle commands if (!m_commands.empty()) { // Look for the first non-switch in the list ArgList::iterator cmd = begin; while (cmd != list.end() && list.isSwitch(cmd)) ++cmd; if (cmd != list.end()) { // A command has been found, ensure that we can handle it map<string, Engine*>::iterator a = m_aliases.find(*cmd); if (a == m_aliases.end()) throw exception::BadOption("unknown command " + *cmd); // Remove the command from the list if (cmd == begin) ++begin; list.erase(cmd); // We found a valid command, let's enable subcommand parsing m_found_command = a->second; } } if (!m_found_command) { // If we don't have any more subcommands to parse, then ensure that // there are no switches left to process for (ArgList::iterator i = begin; i != list.end(); ++i) { if (*i == "--") { // Remove '--' and stop looking for switches if (begin == i) { begin++; list.erase(i); } break; } if (list.isSwitch(i)) throw exception::BadOption(string("unknown option ") + *i); else if (no_switches_after_first_arg) // If requested, stop looking for switches // after the first non-switch argument break; } m_found_command = 0; return begin; } else { // Else, invoke the subcommand engine on the list return m_found_command->parse(list, begin); } }