fp@922: /***************************************************************************** fp@922: * fp@922: * $Id$ fp@922: * fp@922: ****************************************************************************/ fp@922: fp@922: #include fp@1118: #include // basename() fp@922: fp@922: #include fp@1126: #include fp@922: using namespace std; fp@922: fp@1142: #include "CommandAlias.h" fp@1142: #include "CommandConfig.h" fp@1142: #include "CommandData.h" fp@1142: #include "CommandDebug.h" fp@1142: #include "CommandDomains.h" fp@1142: #include "CommandMaster.h" fp@1142: #include "CommandPdos.h" fp@1142: #include "CommandSdos.h" fp@1142: #include "CommandDownload.h" fp@1142: #include "CommandUpload.h" fp@1142: #include "CommandSlaves.h" fp@1142: #include "CommandSiiRead.h" fp@1142: #include "CommandSiiWrite.h" fp@1142: #include "CommandStates.h" fp@1142: #include "CommandXml.h" fp@1122: fp@1122: /*****************************************************************************/ fp@1122: fp@1142: typedef list CommandList; fp@1142: CommandList commandList; fp@1142: fp@1142: MasterDevice masterDev; fp@1142: fp@1122: string binaryBaseName; fp@1142: string commandName; fp@1142: Command::StringVector commandArgs; fp@1142: fp@1142: // option variables fp@1122: unsigned int masterIndex = 0; fp@1122: int slavePosition = -1; fp@1122: int domainIndex = -1; fp@968: string dataTypeStr; fp@1142: Command::Verbosity verbosity = Command::Normal; fp@980: bool force = false; fp@1121: bool helpRequested = false; fp@922: fp@1122: /*****************************************************************************/ fp@1122: fp@1144: string usage() fp@1122: { fp@1144: stringstream str; fp@1142: CommandList::const_iterator ci; fp@1126: size_t maxWidth = 0; fp@1126: fp@1142: for (ci = commandList.begin(); ci != commandList.end(); ci++) { fp@1142: if ((*ci)->getName().length() > maxWidth) { fp@1142: maxWidth = (*ci)->getName().length(); fp@1126: } fp@1126: } fp@1126: fp@1144: str << "Usage: " << binaryBaseName << " [OPTIONS] [ARGUMENTS]" fp@1137: << endl << endl fp@1137: << "Commands (can be abbreviated):" << endl; fp@1126: fp@1144: str << left; fp@1142: for (ci = commandList.begin(); ci != commandList.end(); ci++) { fp@1144: str << " " << setw(maxWidth) << (*ci)->getName() fp@1142: << " " << (*ci)->getBriefDescription() << endl; fp@1126: } fp@1126: fp@1144: str << endl fp@1122: << "Global options:" << endl fp@1137: << " --master -m Index of the master to use. Default: 0." fp@1122: << endl fp@1137: << " --force -f Force a command." << endl fp@1122: << " --quiet -q Output less information." << endl fp@1122: << " --verbose -v Output more information." << endl fp@1122: << " --help -h Show this help." << endl fp@1137: << endl fp@1144: << Command::numericInfo() fp@1137: << endl fp@1122: << "Call '" << binaryBaseName fp@1122: << " --help' for command-specific help." << endl fp@1137: << endl fp@1122: << "Send bug reports to " << PACKAGE_BUGREPORT << "." << endl; fp@1144: fp@1144: return str.str(); fp@1122: } fp@1122: fp@1122: /*****************************************************************************/ fp@1122: fp@1122: void getOptions(int argc, char **argv) fp@1122: { fp@1122: int c, argCount, optionIndex, number; fp@1122: char *remainder; fp@1122: fp@1122: static struct option longOptions[] = { fp@1122: //name, has_arg, flag, val fp@1122: {"master", required_argument, NULL, 'm'}, fp@1122: {"slave", required_argument, NULL, 's'}, fp@1122: {"domain", required_argument, NULL, 'd'}, fp@1122: {"type", required_argument, NULL, 't'}, fp@1122: {"force", no_argument, NULL, 'f'}, fp@1122: {"quiet", no_argument, NULL, 'q'}, fp@1122: {"verbose", no_argument, NULL, 'v'}, fp@1122: {"help", no_argument, NULL, 'h'}, fp@1122: {} fp@1122: }; fp@1122: fp@1122: do { fp@1122: c = getopt_long(argc, argv, "m:s:d:t:fqvh", longOptions, &optionIndex); fp@1122: fp@1122: switch (c) { fp@1122: case 'm': fp@1122: number = strtoul(optarg, &remainder, 0); fp@1122: if (remainder == optarg || *remainder || number < 0) { fp@1144: cerr << "Invalid master number " << optarg << "!" << endl fp@1144: << endl << usage(); fp@1122: exit(1); fp@1122: } fp@1122: masterIndex = number; fp@1122: break; fp@1122: fp@1122: case 's': fp@1122: if (!strcmp(optarg, "all")) { fp@1122: slavePosition = -1; fp@1122: } else { fp@1122: number = strtoul(optarg, &remainder, 0); fp@1122: if (remainder == optarg || *remainder fp@1122: || number < 0 || number > 0xFFFF) { fp@1144: cerr << "Invalid slave position " << optarg << "!" fp@1144: << endl << endl << usage(); fp@1122: exit(1); fp@1122: } fp@1122: slavePosition = number; fp@1122: } fp@1122: break; fp@1122: fp@1122: case 'd': fp@1122: if (!strcmp(optarg, "all")) { fp@1122: domainIndex = -1; fp@1122: } else { fp@1122: number = strtoul(optarg, &remainder, 0); fp@1122: if (remainder == optarg || *remainder || number < 0) { fp@1122: cerr << "Invalid domain index " fp@1144: << optarg << "!" << endl << endl << usage(); fp@1122: exit(1); fp@1122: } fp@1122: domainIndex = number; fp@1122: } fp@1122: break; fp@1122: fp@1122: case 't': fp@1122: dataTypeStr = optarg; fp@1122: break; fp@1122: fp@1122: case 'f': fp@1122: force = true; fp@1122: break; fp@1122: fp@1122: case 'q': fp@1142: verbosity = Command::Quiet; fp@1122: break; fp@1122: fp@1122: case 'v': fp@1142: verbosity = Command::Verbose; fp@1122: break; fp@1122: fp@1122: case 'h': fp@1122: helpRequested = true; fp@1122: break; fp@1122: fp@1122: case '?': fp@1144: cerr << endl << usage(); fp@1122: exit(1); fp@1122: fp@1122: default: fp@1122: break; fp@1122: } fp@1122: } fp@1122: while (c != -1); fp@1122: fp@1122: argCount = argc - optind; fp@1122: fp@1122: if (!argCount) { fp@1144: if (helpRequested) { fp@1144: cout << usage(); fp@1144: exit(0); fp@1144: } else { fp@1144: cerr << "Please specify a command!" << endl fp@1144: << endl << usage(); fp@1144: exit(1); fp@1144: } fp@1122: } fp@1122: fp@1125: commandName = argv[optind]; fp@1122: while (++optind < argc) fp@1122: commandArgs.push_back(string(argv[optind])); fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1142: list getMatchingCommands(const string &cmdStr) fp@1122: { fp@1142: CommandList::iterator ci; fp@1142: list res; fp@1125: fp@1127: // find matching commands from beginning of the string fp@1142: for (ci = commandList.begin(); ci != commandList.end(); ci++) { fp@1142: if ((*ci)->matchesSubstr(cmdStr)) { fp@1142: res.push_back(*ci); fp@1125: } fp@1125: } fp@1125: fp@1127: if (!res.size()) { // nothing found fp@1127: // find /any/ matching commands fp@1142: for (ci = commandList.begin(); ci != commandList.end(); ci++) { fp@1142: if ((*ci)->matchesAbbrev(cmdStr)) { fp@1142: res.push_back(*ci); fp@1127: } fp@1127: } fp@1127: } fp@1127: fp@1125: return res; fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: int main(int argc, char **argv) fp@1122: { fp@1122: int retval = 0; fp@1142: list matchingCommands; fp@1142: list::const_iterator ci; fp@1142: Command *cmd; fp@1122: fp@1122: binaryBaseName = basename(argv[0]); fp@1142: fp@1142: commandList.push_back(new CommandAlias()); fp@1142: commandList.push_back(new CommandConfig()); fp@1142: commandList.push_back(new CommandData()); fp@1142: commandList.push_back(new CommandDebug()); fp@1142: commandList.push_back(new CommandDomains()); fp@1142: commandList.push_back(new CommandDownload()); fp@1142: commandList.push_back(new CommandMaster()); fp@1142: commandList.push_back(new CommandPdos()); fp@1142: commandList.push_back(new CommandSdos()); fp@1142: commandList.push_back(new CommandSiiRead()); fp@1142: commandList.push_back(new CommandSiiWrite()); fp@1142: commandList.push_back(new CommandSlaves()); fp@1142: commandList.push_back(new CommandStates()); fp@1142: commandList.push_back(new CommandUpload()); fp@1142: commandList.push_back(new CommandXml()); fp@1142: fp@1122: getOptions(argc, argv); fp@1122: fp@1142: matchingCommands = getMatchingCommands(commandName); fp@1142: masterDev.setIndex(masterIndex); fp@1142: fp@1142: if (matchingCommands.size()) { fp@1142: if (matchingCommands.size() == 1) { fp@1142: cmd = matchingCommands.front(); fp@1125: if (!helpRequested) { fp@1142: try { fp@1144: cmd->setVerbosity(verbosity); fp@1142: cmd->execute(masterDev, commandArgs); fp@1142: } catch (InvalidUsageException &e) { fp@1142: cerr << e.what() << endl << endl; fp@1144: cerr << binaryBaseName << " " << cmd->helpString(); fp@1142: retval = 1; fp@1142: } catch (CommandException &e) { fp@1142: cerr << e.what() << endl; fp@1142: retval = 1; fp@1142: } catch (MasterDeviceException &e) { fp@1142: cerr << e.what() << endl; fp@1142: retval = 1; fp@1142: } fp@1125: } else { fp@1144: cout << binaryBaseName << " " << cmd->helpString(); fp@1125: } fp@935: } else { fp@1128: cerr << "Ambiguous command abbreviation! Matching:" << endl; fp@1142: for (ci = matchingCommands.begin(); fp@1142: ci != matchingCommands.end(); fp@1142: ci++) { fp@1142: cerr << (*ci)->getName() << endl; fp@1125: } fp@1144: cerr << endl << usage(); fp@1125: retval = 1; fp@935: } fp@1125: } else { fp@1144: cerr << "Unknown command " << commandName << "!" << endl fp@1144: << endl << usage(); fp@1122: retval = 1; fp@922: } fp@922: fp@1122: return retval; fp@922: } fp@922: fp@922: /****************************************************************************/