# HG changeset patch # User Martin Troxler # Date 1300098005 -3600 # Node ID 8b358effa78b9ac6222c326bb7dbe863ca710dab # Parent f5b31f46c38f1f86a393b3bc9079656b09230850# Parent ce2fae4d3c4fae6a3cb6d8a91a3df9bbb272ff82 merged diff -r f5b31f46c38f -r 8b358effa78b TODO --- a/TODO Thu Feb 24 10:04:42 2011 +0100 +++ b/TODO Mon Mar 14 11:20:05 2011 +0100 @@ -13,17 +13,12 @@ * 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 -r f5b31f46c38f -r 8b358effa78b include/ecrt.h --- a/include/ecrt.h Thu Feb 24 10:04:42 2011 +0100 +++ b/include/ecrt.h Mon Mar 14 11:20:05 2011 +0100 @@ -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 @@ 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 -r f5b31f46c38f -r 8b358effa78b lib/master.c --- a/lib/master.c Thu Feb 24 10:04:42 2011 +0100 +++ b/lib/master.c Mon Mar 14 11:20:05 2011 +0100 @@ -591,3 +591,12 @@ } /*****************************************************************************/ + +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 -r f5b31f46c38f -r 8b358effa78b master/cdev.c --- a/master/cdev.c Thu Feb 24 10:04:42 2011 +0100 +++ b/master/cdev.c Mon Mar 14 11:20:05 2011 +0100 @@ -2009,6 +2009,25 @@ /*****************************************************************************/ +/** 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 @@ 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 -r f5b31f46c38f -r 8b358effa78b master/ioctl.h --- a/master/ioctl.h Thu Feb 24 10:04:42 2011 +0100 +++ b/master/ioctl.h Mon Mar 14 11:20:05 2011 +0100 @@ -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 -r f5b31f46c38f -r 8b358effa78b master/master.c --- a/master/master.c Thu Feb 24 10:04:42 2011 +0100 +++ b/master/master.c Mon Mar 14 11:20:05 2011 +0100 @@ -2475,6 +2475,19 @@ /*****************************************************************************/ +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_process); EXPORT_SYMBOL(ecrt_master_write_idn); EXPORT_SYMBOL(ecrt_master_read_idn); +EXPORT_SYMBOL(ecrt_master_reset); /** \endcond */ diff -r f5b31f46c38f -r 8b358effa78b tool/Command.cpp --- a/tool/Command.cpp Thu Feb 24 10:04:42 2011 +0100 +++ b/tool/Command.cpp Mon Mar 14 11:20:05 2011 +0100 @@ -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::setAlias(int a) -{ - alias = a; -}; - -/*****************************************************************************/ - -void Command::setPosition(int p) -{ - position = p; -}; - -/*****************************************************************************/ - -void Command::setDomain(int d) -{ - domain = d; +void Command::setAliases(const string &a) +{ + aliases = a; +}; + +/*****************************************************************************/ + +void Command::setPositions(const string &p) +{ + positions = p; +}; + +/*****************************************************************************/ + +void Command::setDomains(const string &d) +{ + domains = d; }; /*****************************************************************************/ @@ -214,11 +312,13 @@ 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 @@ 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 @@ 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 { // 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); - } - } - } 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 + } 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; + } + } + + 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; + } + + 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::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); - - for (i = 0; i < master.domain_count; i++) { - m.getDomain(&d, i); + m.getMaster(&master); + + PositionParser pp(master.domain_count); + NumberListParser::List domList = pp.parse(domains.c_str()); + NumberListParser::List::const_iterator di; + + 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 -r f5b31f46c38f -r 8b358effa78b tool/Command.h --- a/tool/Command.h Thu Feb 24 10:04:42 2011 +0100 +++ b/tool/Command.h Mon Mar 14 11:20:05 2011 +0100 @@ -96,16 +96,20 @@ }; 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 @@ 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 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 -r f5b31f46c38f -r 8b358effa78b tool/NumberListParser.cpp --- a/tool/NumberListParser.cpp Thu Feb 24 10:04:42 2011 +0100 +++ b/tool/NumberListParser.cpp Mon Mar 14 11:20:05 2011 +0100 @@ -50,9 +50,9 @@ /*****************************************************************************/ -NumberListParser::NumberList NumberListParser::parse(const char *data) -{ - NumberList ret; +NumberListParser::List NumberListParser::parse(const char *data) +{ + List ret; unsigned int i = 0, size = strlen(data), firstNum = 0U, secondNum = 0U; typedef enum { SectionStart, @@ -108,17 +108,41 @@ 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] == ',') { - i++; - secondNum = maximum(); - NumberList r = range(firstNum, secondNum); + int max = maximum(); + i++; + if (max >= 0) { + List r = range(firstNum, max); + ret.splice(ret.end(), r); + } + state = SectionStart; + } else { + stringstream err; + err << "Invalid character " << data[i] + << " at position " << i << "in state " + << state << "." << endl; + throw runtime_error(err.str()); + } + break; + + case SecondNumber: + if (i >= size) { + List r = range(firstNum, secondNum); + ret.splice(ret.end(), r); + state = Finished; + } else if (data[i] == ',') { + i++; + List r = range(firstNum, secondNum); ret.splice(ret.end(), r); state = SectionStart; } else { @@ -130,25 +154,6 @@ } break; - case SecondNumber: - if (i >= size) { - NumberList r = range(firstNum, secondNum); - ret.splice(ret.end(), r); - state = Finished; - } else if (data[i] == ',') { - i++; - NumberList r = range(firstNum, secondNum); - ret.splice(ret.end(), r); - state = SectionStart; - } else { - stringstream err; - err << "Invalid character " << data[i] - << " at position " << i << "in state " - << state << "." << endl; - throw runtime_error(err.str()); - } - break; - default: { stringstream err; @@ -163,7 +168,7 @@ /*****************************************************************************/ -unsigned int NumberListParser::maximum() +int NumberListParser::maximum() { if (!hasMax) { max = getMax(); @@ -207,12 +212,12 @@ /****************************************************************************/ -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 -r f5b31f46c38f -r 8b358effa78b tool/NumberListParser.h --- a/tool/NumberListParser.h Thu Feb 24 10:04:42 2011 +0100 +++ b/tool/NumberListParser.h Mon Mar 14 11:20:05 2011 +0100 @@ -38,22 +38,22 @@ 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 -r f5b31f46c38f -r 8b358effa78b tool/main.cpp --- a/tool/main.cpp Thu Feb 24 10:04:42 2011 +0100 +++ b/tool/main.cpp Mon Mar 14 11:20:05 2011 +0100 @@ -77,9 +77,9 @@ // 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 @@ 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 @@ 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);