fp@922: /***************************************************************************** fp@922: * fp@1363: * $Id$ fp@1363: * fp@1363: * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH fp@1363: * fp@1363: * This file is part of the IgH EtherCAT Master. fp@1363: * fp@1363: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1363: * modify it under the terms of the GNU General Public License version 2, as fp@1363: * published by the Free Software Foundation. fp@1363: * fp@1363: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1363: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1363: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1363: * Public License for more details. fp@1363: * fp@1363: * You should have received a copy of the GNU General Public License along fp@1363: * with the IgH EtherCAT Master; if not, write to the Free Software fp@1363: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1363: * fp@1363: * --- fp@1363: * fp@1363: * The license mentioned above concerns the source code only. Using the fp@1363: * EtherCAT technology and brand is only permitted in compliance with the fp@1363: * industrial property and similar rights of Beckhoff Automation GmbH. fp@922: * fp@922: ****************************************************************************/ fp@922: fp@922: #include fp@1118: #include // basename() fp@1222: #include 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@1514: #include "CommandCStruct.h" fp@1142: #include "CommandData.h" fp@1142: #include "CommandDebug.h" fp@1142: #include "CommandDomains.h" fp@1165: #include "CommandDownload.h" fp@1485: #include "CommandEoe.h" fp@1335: #include "CommandFoeRead.h" fp@1335: #include "CommandFoeWrite.h" fp@1422: #include "CommandGraph.h" fp@1142: #include "CommandMaster.h" fp@1142: #include "CommandPdos.h" fp@1388: #include "CommandRegRead.h" fp@1388: #include "CommandRegWrite.h" fp@1142: #include "CommandSdos.h" fp@1142: #include "CommandSiiRead.h" fp@1142: #include "CommandSiiWrite.h" fp@1165: #include "CommandSlaves.h" fp@1142: #include "CommandStates.h" fp@1165: #include "CommandUpload.h" fp@1165: #include "CommandVersion.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@1151: int slaveAlias = -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@1335: string outputFile; 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@1158: int c, argCount; fp@1158: stringstream str; fp@1122: fp@1122: static struct option longOptions[] = { fp@1335: //name, has_arg, flag, val fp@1335: {"master", required_argument, NULL, 'm'}, fp@1335: {"alias", required_argument, NULL, 'a'}, fp@1335: {"position", required_argument, NULL, 'p'}, fp@1335: {"domain", required_argument, NULL, 'd'}, fp@1335: {"type", required_argument, NULL, 't'}, fp@1335: {"output-file", required_argument, NULL, 'o'}, fp@1335: {"force", no_argument, NULL, 'f'}, fp@1335: {"quiet", no_argument, NULL, 'q'}, fp@1335: {"verbose", no_argument, NULL, 'v'}, fp@1335: {"help", no_argument, NULL, 'h'}, fp@1122: {} fp@1122: }; fp@1122: fp@1122: do { fp@1335: c = getopt_long(argc, argv, "m:a:p:d:t:o:fqvh", longOptions, NULL); fp@1122: fp@1122: switch (c) { fp@1122: case 'm': fp@1158: str.clear(); fp@1158: str.str(""); fp@1158: str << optarg; fp@1158: str >> resetiosflags(ios::basefield) // guess base from prefix fp@1158: >> masterIndex; fp@1158: if (str.fail() || masterIndex < 0) { fp@1144: cerr << "Invalid master number " << optarg << "!" << endl fp@1144: << endl << usage(); fp@1122: exit(1); fp@1122: } fp@1122: break; fp@1122: fp@1151: case 'a': fp@1158: str.clear(); fp@1158: str.str(""); fp@1158: str << optarg; fp@1158: str >> resetiosflags(ios::basefield) // guess base from prefix fp@1158: >> slaveAlias; fp@1158: if (str.fail() || slaveAlias < 0 || slaveAlias > 0xFFFF) { fp@1158: cerr << "Invalid slave alias " << optarg << "!" << endl fp@1158: << endl << usage(); fp@1158: exit(1); fp@1151: } fp@1151: break; fp@1151: fp@1151: case 'p': fp@1158: str.clear(); fp@1158: str.str(""); fp@1158: str << optarg; fp@1158: str >> resetiosflags(ios::basefield) // guess base from prefix fp@1158: >> slavePosition; fp@1158: if (str.fail() fp@1158: || slavePosition < 0 || slavePosition > 0xFFFF) { fp@1158: cerr << "Invalid slave position " << optarg << "!" << endl fp@1158: << endl << usage(); fp@1158: exit(1); fp@1122: } fp@1122: break; fp@1122: fp@1122: case 'd': fp@1158: str.clear(); fp@1158: str.str(""); fp@1158: str << optarg; fp@1158: str >> resetiosflags(ios::basefield) // guess base from prefix fp@1158: >> domainIndex; fp@1158: if (str.fail() || domainIndex < 0) { fp@1158: cerr << "Invalid domain index " << optarg << "!" << endl fp@1158: << endl << usage(); fp@1158: exit(1); fp@1122: } fp@1122: break; fp@1122: fp@1122: case 't': fp@1122: dataTypeStr = optarg; fp@1122: break; fp@1122: fp@1335: case 'o': fp@1335: outputFile = optarg; fp@1335: break; fp@1335: 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@1514: commandList.push_back(new CommandCStruct()); 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@1485: commandList.push_back(new CommandEoe()); fp@1335: commandList.push_back(new CommandFoeRead()); fp@1335: commandList.push_back(new CommandFoeWrite()); fp@1422: commandList.push_back(new CommandGraph()); fp@1142: commandList.push_back(new CommandMaster()); fp@1142: commandList.push_back(new CommandPdos()); fp@1388: commandList.push_back(new CommandRegRead()); fp@1388: commandList.push_back(new CommandRegWrite()); 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@1165: commandList.push_back(new CommandVersion()); 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@1151: cmd->setAlias(slaveAlias); fp@1151: cmd->setPosition(slavePosition); fp@1166: cmd->setDomain(domainIndex); fp@1166: cmd->setDataType(dataTypeStr); fp@1335: cmd->setOutputFile(outputFile); fp@1166: cmd->setForce(force); 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: /****************************************************************************/