diff --git a/TODO b/TODO index c9974efe..9bcaa9c7 100644 --- a/TODO +++ b/TODO @@ -13,17 +13,12 @@ Version 1.5.0: * Ethernet drivers: - Fix link detection in generic driver. - Add native drivers from 2.6.24 up to 2.6.31. -* ethercat tool: - - Implement ranges for slaves and domains. Future issues: * Remove allow_scanning flag. -* Output skipped datagrams again. * Check for Enable SDO Complete Access flag. * Do not output 'SDO does not exist' when querying data type. -* Always write down PDO assignment/mapping in doubt? If not, add an interface - for enforcing this. * Read AL status code on spontaneous state change. * recompile tool/CommandVersion.cpp if revision changes. * Log SoE IDNs with real name ([SP]-x-yyyy). diff --git a/include/ecrt.h b/include/ecrt.h index 7b1d9f6f..a5d96a8a 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -76,6 +76,7 @@ * - Added ecrt_slave_config_idn() method for storing SoE IDN configurations, * and ecrt_master_read_idn() and ecrt_master_write_idn() to read/write IDNs * ad-hoc via the user-space library. + * - Added ecrt_master_reset() to initiate retrying to configure slaves. * - Added support for overlapping PDOs which allows inputs to use the same * space as outputs on the frame. This reduces the frame length. * @@ -885,6 +886,17 @@ uint32_t ecrt_master_sync_monitor_process( ec_master_t *master /**< EtherCAT master. */ ); +/** Retry configuring slaves. + * + * Via this method, the application can tell the master to bring all slaves to + * OP state. In general, this is not necessary, because it is automatically + * done by the master. But with special slaves, that can be reconfigured by + * the vendor during runtime, it can be useful. + */ +void ecrt_master_reset( + ec_master_t *master /**< EtherCAT master. */ + ); + /****************************************************************************** * Slave configuration methods *****************************************************************************/ diff --git a/lib/master.c b/lib/master.c index e3ed8f3d..5a538fda 100644 --- a/lib/master.c +++ b/lib/master.c @@ -591,3 +591,12 @@ uint32_t ecrt_master_sync_monitor_process(ec_master_t *master) } /*****************************************************************************/ + +void ecrt_master_reset(ec_master_t *master) +{ + if (ioctl(master->fd, EC_IOCTL_RESET, NULL) == -1) { + fprintf(stderr, "Failed to reset master: %s\n", strerror(errno)); + } +} + +/*****************************************************************************/ diff --git a/master/cdev.c b/master/cdev.c index 4e292378..9373d873 100644 --- a/master/cdev.c +++ b/master/cdev.c @@ -2009,6 +2009,25 @@ int ec_cdev_ioctl_sync_mon_process( /*****************************************************************************/ +/** Reset configuration. + */ +int ec_cdev_ioctl_reset( + ec_master_t *master, /**< EtherCAT master. */ + unsigned long arg, /**< ioctl() argument. */ + ec_cdev_priv_t *priv /**< Private data structure of file handle. */ + ) +{ + if (unlikely(!priv->requested)) + return -EPERM; + + ec_mutex_lock(&master->master_mutex); + ecrt_master_reset(master); + ec_mutex_unlock(&master->master_mutex); + return 0; +} + +/*****************************************************************************/ + /** Configure a sync manager. */ int ec_cdev_ioctl_sc_sync( @@ -3723,6 +3742,10 @@ long eccdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; return ec_cdev_ioctl_sync_mon_process(master, arg, priv); + case EC_IOCTL_RESET: + if (!(filp->f_mode & FMODE_WRITE)) + return -EPERM; + return ec_cdev_ioctl_reset(master, arg, priv); case EC_IOCTL_SC_SYNC: if (!(filp->f_mode & FMODE_WRITE)) return -EPERM; diff --git a/master/ioctl.h b/master/ioctl.h index 45767b4d..43f68b6d 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -56,7 +56,7 @@ * * Increment this when changing the ioctl interface! */ -#define EC_IOCTL_VERSION_MAGIC 11 +#define EC_IOCTL_VERSION_MAGIC 12 // Command-line tool #define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t) @@ -95,7 +95,7 @@ // Application interface #define EC_IOCTL_REQUEST EC_IO(0x1e) #define EC_IOCTL_CREATE_DOMAIN EC_IO(0x1f) -#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x10, ec_ioctl_config_t) +#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x20, ec_ioctl_config_t) #define EC_IOCTL_ACTIVATE EC_IOR(0x21, size_t) #define EC_IOCTL_DEACTIVATE EC_IO(0x22) #define EC_IOCTL_SEND EC_IO(0x23) @@ -106,38 +106,39 @@ #define EC_IOCTL_SYNC_SLAVES EC_IO(0x28) #define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x29) #define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x2a, uint32_t) -#define EC_IOCTL_SC_SYNC EC_IOW(0x2b, ec_ioctl_config_t) -#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x2c, ec_ioctl_config_t) -#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x2d, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x2e, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x2f, ec_ioctl_add_pdo_entry_t) -#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x20, ec_ioctl_config_pdo_t) -#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x21, ec_ioctl_reg_pdo_entry_t) -#define EC_IOCTL_SC_DC EC_IOW(0x32, ec_ioctl_config_t) -#define EC_IOCTL_SC_SDO EC_IOW(0x33, ec_ioctl_sc_sdo_t) -#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x34, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SC_VOE EC_IOWR(0x35, ec_ioctl_voe_t) -#define EC_IOCTL_SC_STATE EC_IOWR(0x36, ec_ioctl_sc_state_t) -#define EC_IOCTL_SC_IDN EC_IOW(0x37, ec_ioctl_sc_idn_t) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x38) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x39) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3a) -#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3b, ec_ioctl_domain_state_t) -#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3c, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x3d, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x3e, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x3f, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x30, ec_ioctl_sdo_request_t) -#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x41, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x42, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ EC_IOW(0x43, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x44, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_WRITE EC_IOWR(0x45, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_EXEC EC_IOWR(0x46, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_DATA EC_IOWR(0x47, ec_ioctl_voe_t) -#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x48, size_t) -#define EC_IOCTL_MASTER_SC_STATE EC_IOR(0x49, ec_master_state_t) -#define EC_IOCTL_SC_OVERLAPPING_IO EC_IOW(0x50, ec_ioctl_config_t) +#define EC_IOCTL_RESET EC_IO(0x2b) +#define EC_IOCTL_SC_SYNC EC_IOW(0x2c, ec_ioctl_config_t) +#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x2d, ec_ioctl_config_t) +#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x2e, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x2f, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x30, ec_ioctl_add_pdo_entry_t) +#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x31, ec_ioctl_config_pdo_t) +#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x32, ec_ioctl_reg_pdo_entry_t) +#define EC_IOCTL_SC_DC EC_IOW(0x33, ec_ioctl_config_t) +#define EC_IOCTL_SC_SDO EC_IOW(0x34, ec_ioctl_sc_sdo_t) +#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x35, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SC_VOE EC_IOWR(0x36, ec_ioctl_voe_t) +#define EC_IOCTL_SC_STATE EC_IOWR(0x37, ec_ioctl_sc_state_t) +#define EC_IOCTL_SC_IDN EC_IOW(0x38, ec_ioctl_sc_idn_t) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x39) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x3a) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x3b) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x3c, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x3d, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x3e, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x3f, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x40, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x41, ec_ioctl_sdo_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x42, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x43, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x44, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x45, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x46, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x47, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x48, ec_ioctl_voe_t) +#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x49, size_t) +#define EC_IOCTL_MASTER_SC_STATE EC_IOR(0x50, ec_master_state_t) +#define EC_IOCTL_SC_OVERLAPPING_IO EC_IOW(0x51, ec_ioctl_config_t) /*****************************************************************************/ diff --git a/master/master.c b/master/master.c index a44aca79..39caba9b 100644 --- a/master/master.c +++ b/master/master.c @@ -2475,6 +2475,19 @@ int ecrt_master_read_idn(ec_master_t *master, uint16_t slave_position, /*****************************************************************************/ +void ecrt_master_reset(ec_master_t *master) +{ + ec_slave_config_t *sc; + + list_for_each_entry(sc, &master->configs, list) { + if (sc->slave) { + ec_slave_request_state(sc->slave, EC_SLAVE_STATE_OP); + } + } +} + +/*****************************************************************************/ + /** \cond */ EXPORT_SYMBOL(ecrt_master_create_domain); @@ -2494,6 +2507,7 @@ EXPORT_SYMBOL(ecrt_master_sync_monitor_queue); EXPORT_SYMBOL(ecrt_master_sync_monitor_process); EXPORT_SYMBOL(ecrt_master_write_idn); EXPORT_SYMBOL(ecrt_master_read_idn); +EXPORT_SYMBOL(ecrt_master_reset); /** \endcond */ diff --git a/tool/Command.cpp b/tool/Command.cpp index 12d35c68..de9e246c 100644 --- a/tool/Command.cpp +++ b/tool/Command.cpp @@ -29,22 +29,120 @@ * ****************************************************************************/ +#include +using namespace std; + #include "Command.h" #include "MasterDevice.h" #include "NumberListParser.h" /*****************************************************************************/ +typedef map AliasMap; +typedef map ConfigMap; + +/*****************************************************************************/ + class MasterIndexParser: public NumberListParser { - unsigned int getMax() - { - MasterDevice dev; - dev.setIndex(0U); - dev.open(MasterDevice::Read); - return dev.getMasterCount() - 1; - }; + protected: + int getMax() { + MasterDevice dev; + dev.setIndex(0U); + dev.open(MasterDevice::Read); + return (int) dev.getMasterCount() - 1; + }; +}; + +/*****************************************************************************/ + +class SlaveAliasParser: + public NumberListParser +{ + public: + SlaveAliasParser(ec_ioctl_master_t &master, MasterDevice &dev): + master(master), dev(dev) {} + + protected: + int getMax() { + unsigned int i; + + uint16_t maxAlias = 0; + for (i = 0; i < master.slave_count; i++) { + ec_ioctl_slave_t slave; + dev.getSlave(&slave, i); + if (slave.alias > maxAlias) { + maxAlias = slave.alias; + } + } + return maxAlias ? maxAlias : -1; + }; + + private: + ec_ioctl_master_t &master; + MasterDevice &dev; +}; + +/*****************************************************************************/ + +class ConfigAliasParser: + public NumberListParser +{ + public: + ConfigAliasParser(unsigned int maxAlias): + maxAlias(maxAlias) {} + + protected: + int getMax() { return maxAlias; }; + + private: + unsigned int maxAlias; +}; + +/*****************************************************************************/ + +class PositionParser: + public NumberListParser +{ + public: + PositionParser(unsigned int count): + count(count) {} + + protected: + int getMax() { + return count - 1; + }; + + private: + const unsigned int count; +}; + +/*****************************************************************************/ + +class AliasPositionParser: + public NumberListParser +{ + public: + AliasPositionParser(const AliasMap &aliasMap): + aliasMap(aliasMap) {} + + protected: + int getMax() { + AliasMap::const_iterator i; + int maxPos = -1; + + for (i = aliasMap.begin(); i != aliasMap.end(); i++) { + if (i->first > maxPos) { + maxPos = i->first; + } + } + + return maxPos; + }; + + private: + const AliasMap &aliasMap; }; /*****************************************************************************/ @@ -78,23 +176,23 @@ void Command::setVerbosity(Verbosity v) /*****************************************************************************/ -void Command::setAlias(int a) +void Command::setAliases(const string &a) { - alias = a; + aliases = a; }; /*****************************************************************************/ -void Command::setPosition(int p) +void Command::setPositions(const string &p) { - position = p; + positions = p; }; /*****************************************************************************/ -void Command::setDomain(int d) +void Command::setDomains(const string &d) { - domain = d; + domains = d; }; /*****************************************************************************/ @@ -214,11 +312,13 @@ Command::MasterIndexList Command::getMasterIndices() const unsigned int Command::getSingleMasterIndex() const { MasterIndexList masterIndices = getMasterIndices(); + if (masterIndices.size() != 1) { stringstream err; err << getName() << " requires to select a single master!"; throwInvalidUsageException(err); } + return masterIndices.front(); } @@ -227,51 +327,57 @@ unsigned int Command::getSingleMasterIndex() const Command::SlaveList Command::selectedSlaves(MasterDevice &m) { ec_ioctl_master_t master; - unsigned int i, aliasIndex; - uint16_t lastAlias; + unsigned int i; ec_ioctl_slave_t slave; SlaveList list; m.getMaster(&master); - if (alias == -1) { // no alias given - if (position == -1) { // no alias and position given - // all items - for (i = 0; i < master.slave_count; i++) { - m.getSlave(&slave, i); + if (aliases == "-") { // no alias given + PositionParser pp(master.slave_count); + NumberListParser::List posList = pp.parse(positions.c_str()); + NumberListParser::List::const_iterator pi; + + for (pi = posList.begin(); pi != posList.end(); pi++) { + if (*pi < master.slave_count) { + m.getSlave(&slave, *pi); list.push_back(slave); } - } else { // no alias, but position given - // one item by position - m.getSlave(&slave, position); - list.push_back(slave); } - } else { // alias given - if (position == -1) { // alias, but no position given - // take all items with a given alias - lastAlias = 0; + } else { // aliases given + SlaveAliasParser ap(master, m); + NumberListParser::List aliasList = ap.parse(aliases.c_str()); + NumberListParser::List::const_iterator ai; + + for (ai = aliasList.begin(); ai != aliasList.end(); ai++) { + + // gather slaves with that alias (and following) + uint16_t lastAlias = 0; + vector aliasSlaves; + for (i = 0; i < master.slave_count; i++) { m.getSlave(&slave, i); if (slave.alias) { + if (lastAlias && lastAlias == *ai && slave.alias != *ai) { + // ignore multiple ocurrences of the same alias to + // assure consistency for the position argument + break; + } lastAlias = slave.alias; } - if (lastAlias == (uint16_t) alias) { - list.push_back(slave); + if (lastAlias == *ai) { + aliasSlaves.push_back(slave); } } - } else { // alias and position given - lastAlias = 0; - aliasIndex = 0; - for (i = 0; i < master.slave_count; i++) { - m.getSlave(&slave, i); - if (slave.alias && slave.alias == (uint16_t) alias) { - lastAlias = slave.alias; - aliasIndex = 0; + + PositionParser pp(aliasSlaves.size()); + NumberListParser::List posList = pp.parse(positions.c_str()); + NumberListParser::List::const_iterator pi; + + for (pi = posList.begin(); pi != posList.end(); pi++) { + if (*pi < aliasSlaves.size()) { + list.push_back(aliasSlaves[*pi]); } - if (lastAlias && aliasIndex == (unsigned int) position) { - list.push_back(slave); - } - aliasIndex++; } } } @@ -302,37 +408,47 @@ Command::ConfigList Command::selectedConfigs(MasterDevice &m) m.getMaster(&master); - if (alias == -1) { // no alias given - if (position == -1) { // no alias and position given - // all items - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - list.push_back(config); - } - } else { // no alias, but position given - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - if (!config.alias && config.position == position) { - list.push_back(config); - break; // there can be at most one matching - } + if (aliases == "-" && positions == "-") { // shortcut + for (i = 0; i < master.config_count; i++) { + m.getConfig(&config, i); + list.push_back(config); + } + } else { // take the long way home... + ConfigMap configs; + uint16_t maxAlias = 0; + + // fill cascaded map structure with all configs + for (i = 0; i < master.config_count; i++) { + m.getConfig(&config, i); + AliasMap &aliasMap = configs[config.alias]; + aliasMap[config.position] = config; + if (config.alias > maxAlias) { + maxAlias = config.alias; } } - } else { // alias given - if (position == -1) { // alias, but no position given - // take all items with a given alias - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - if (config.alias == alias) { - list.push_back(config); - } + + ConfigAliasParser ap(maxAlias); + NumberListParser::List aliasList = ap.parse(aliases.c_str()); + NumberListParser::List::const_iterator ai; + + for (ai = aliasList.begin(); ai != aliasList.end(); ai++) { + + ConfigMap::iterator ci = configs.find(*ai); + if (ci == configs.end()) { + continue; } - } else { // alias and position given - for (i = 0; i < master.config_count; i++) { - m.getConfig(&config, i); - if (config.alias == alias && config.position == position) { - list.push_back(config); - break; // there can be at most one matching + + AliasMap &aliasMap = configs[*ai]; + AliasPositionParser pp(aliasMap); + NumberListParser::List posList = pp.parse(positions.c_str()); + NumberListParser::List::const_iterator pi; + + for (pi = posList.begin(); pi != posList.end(); pi++) { + AliasMap::const_iterator ci; + + ci = aliasMap.find(*pi); + if (ci != aliasMap.end()) { + list.push_back(ci->second); } } } @@ -346,22 +462,21 @@ Command::ConfigList Command::selectedConfigs(MasterDevice &m) Command::DomainList Command::selectedDomains(MasterDevice &m) { - ec_ioctl_domain_t d; + ec_ioctl_master_t master; DomainList list; - if (domain == -1) { - ec_ioctl_master_t master; - unsigned int i; + m.getMaster(&master); - m.getMaster(&master); + PositionParser pp(master.domain_count); + NumberListParser::List domList = pp.parse(domains.c_str()); + NumberListParser::List::const_iterator di; - for (i = 0; i < master.domain_count; i++) { - m.getDomain(&d, i); + for (di = domList.begin(); di != domList.end(); di++) { + if (*di < master.domain_count) { + ec_ioctl_domain_t d; + m.getDomain(&d, *di); list.push_back(d); } - } else { - m.getDomain(&d, domain); - list.push_back(d); } return list; diff --git a/tool/Command.h b/tool/Command.h index 02d70f45..fcb1700f 100644 --- a/tool/Command.h +++ b/tool/Command.h @@ -96,16 +96,20 @@ class Command }; void setVerbosity(Verbosity); Verbosity getVerbosity() const; - void setAlias(int); - int getAlias() const; - void setPosition(int); - int getPosition() const; - void setDomain(int); - int getDomain() const; + + void setAliases(const string &); + void setPositions(const string &); + + void setDomains(const string &); + typedef list DomainIndexList; + DomainIndexList getDomainIndices() const; + void setDataType(const string &); const string &getDataType() const; + void setForce(bool); bool getForce() const; + void setOutputFile(const string &); const string &getOutputFile() const; @@ -141,9 +145,9 @@ class Command string briefDesc; string masters; Verbosity verbosity; - int alias; - int position; - int domain; + string aliases; + string positions; + string domains; string dataType; bool force; string outputFile; @@ -174,27 +178,6 @@ inline Command::Verbosity Command::getVerbosity() const /****************************************************************************/ -inline int Command::getAlias() const -{ - return alias; -} - -/****************************************************************************/ - -inline int Command::getPosition() const -{ - return position; -} - -/****************************************************************************/ - -inline int Command::getDomain() const -{ - return domain; -} - -/****************************************************************************/ - inline const string &Command::getDataType() const { return dataType; diff --git a/tool/NumberListParser.cpp b/tool/NumberListParser.cpp index bdef69f1..9744a763 100644 --- a/tool/NumberListParser.cpp +++ b/tool/NumberListParser.cpp @@ -50,9 +50,9 @@ NumberListParser::~NumberListParser() /*****************************************************************************/ -NumberListParser::NumberList NumberListParser::parse(const char *data) +NumberListParser::List NumberListParser::parse(const char *data) { - NumberList ret; + List ret; unsigned int i = 0, size = strlen(data), firstNum = 0U, secondNum = 0U; typedef enum { SectionStart, @@ -108,18 +108,23 @@ NumberListParser::NumberList NumberListParser::parse(const char *data) case Range: if (i >= size) { - secondNum = maximum(); - NumberList r = range(firstNum, secondNum); - ret.splice(ret.end(), r); + int max = maximum(); + // only increasing ranges if second number omitted + if (max >= 0 && firstNum <= (unsigned int) max) { + List r = range(firstNum, max); + ret.splice(ret.end(), r); + } state = Finished; } else if (isNumeric(data[i])) { secondNum = parseNumber(data, &i, size); state = SecondNumber; } else if (data[i] == ',') { + int max = maximum(); i++; - secondNum = maximum(); - NumberList r = range(firstNum, secondNum); - ret.splice(ret.end(), r); + if (max >= 0) { + List r = range(firstNum, max); + ret.splice(ret.end(), r); + } state = SectionStart; } else { stringstream err; @@ -132,12 +137,12 @@ NumberListParser::NumberList NumberListParser::parse(const char *data) case SecondNumber: if (i >= size) { - NumberList r = range(firstNum, secondNum); + List r = range(firstNum, secondNum); ret.splice(ret.end(), r); state = Finished; } else if (data[i] == ',') { i++; - NumberList r = range(firstNum, secondNum); + List r = range(firstNum, secondNum); ret.splice(ret.end(), r); state = SectionStart; } else { @@ -163,7 +168,7 @@ NumberListParser::NumberList NumberListParser::parse(const char *data) /*****************************************************************************/ -unsigned int NumberListParser::maximum() +int NumberListParser::maximum() { if (!hasMax) { max = getMax(); @@ -207,12 +212,12 @@ unsigned int NumberListParser::parseNumber( /****************************************************************************/ -NumberListParser::NumberList NumberListParser::range( +NumberListParser::List NumberListParser::range( unsigned int i, unsigned int j ) { - NumberList ret; + List ret; if (i <= j) { for (; i <= j; i++) { diff --git a/tool/NumberListParser.h b/tool/NumberListParser.h index 6cf0dd16..ec30aa67 100644 --- a/tool/NumberListParser.h +++ b/tool/NumberListParser.h @@ -38,22 +38,22 @@ class NumberListParser NumberListParser(); virtual ~NumberListParser(); - typedef list NumberList; + typedef list List; - NumberList parse(const char *); + List parse(const char *); - virtual unsigned int getMax() = 0; + virtual int getMax() = 0; private: - unsigned int max; + int max; bool hasMax; - unsigned int maximum(); + int maximum(); static bool isNumeric(char); static unsigned int parseNumber(const char *, unsigned int *, unsigned int); - static NumberList range(unsigned int, unsigned int); + static List range(unsigned int, unsigned int); }; /****************************************************************************/ diff --git a/tool/main.cpp b/tool/main.cpp index c4fa59d0..b03851f1 100644 --- a/tool/main.cpp +++ b/tool/main.cpp @@ -77,9 +77,9 @@ Command::StringVector commandArgs; // option variables string masters = "-"; // all masters -int slavePosition = -1; -int slaveAlias = -1; -int domainIndex = -1; +string positions = "-"; // all positions +string aliases = "-"; // all aliases +string domains = "-"; // all domains string dataTypeStr; Command::Verbosity verbosity = Command::Normal; bool force = false; @@ -163,43 +163,15 @@ void getOptions(int argc, char **argv) break; case 'a': - str.clear(); - str.str(""); - str << optarg; - str >> resetiosflags(ios::basefield) // guess base from prefix - >> slaveAlias; - if (str.fail() || slaveAlias < 0 || slaveAlias > 0xFFFF) { - cerr << "Invalid slave alias " << optarg << "!" << endl - << endl << usage(); - exit(1); - } + aliases = optarg; break; case 'p': - str.clear(); - str.str(""); - str << optarg; - str >> resetiosflags(ios::basefield) // guess base from prefix - >> slavePosition; - if (str.fail() - || slavePosition < 0 || slavePosition > 0xFFFF) { - cerr << "Invalid slave position " << optarg << "!" << endl - << endl << usage(); - exit(1); - } + positions = optarg; break; case 'd': - str.clear(); - str.str(""); - str << optarg; - str >> resetiosflags(ios::basefield) // guess base from prefix - >> domainIndex; - if (str.fail() || domainIndex < 0) { - cerr << "Invalid domain index " << optarg << "!" << endl - << endl << usage(); - exit(1); - } + domains = optarg; break; case 't': @@ -331,9 +303,9 @@ int main(int argc, char **argv) try { cmd->setMasters(masters); cmd->setVerbosity(verbosity); - cmd->setAlias(slaveAlias); - cmd->setPosition(slavePosition); - cmd->setDomain(domainIndex); + cmd->setAliases(aliases); + cmd->setPositions(positions); + cmd->setDomains(domains); cmd->setDataType(dataTypeStr); cmd->setOutputFile(outputFile); cmd->setForce(force);