diff --git a/debuggers/common/registers/registercontroller.cpp b/debuggers/common/registers/registercontroller.cpp index ae26b94ab5..872612b782 100644 --- a/debuggers/common/registers/registercontroller.cpp +++ b/debuggers/common/registers/registercontroller.cpp @@ -1,406 +1,406 @@ /* * Class to fetch/change/send registers to the debugger. * Copyright 2013 Vlas Puhov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #include "registercontroller.h" #include "converters.h" #include "debuglog.h" #include "midebugsession.h" #include "mi/mi.h" #include "mi/micommand.h" #include #include using namespace KDevMI::MI; using namespace KDevMI; void IRegisterController::setSession(MIDebugSession* debugSession) { m_debugSession = debugSession; } void IRegisterController::updateRegisters(const GroupsName& group) { if (!m_debugSession || m_debugSession->debuggerStateIsOn(s_dbgNotStarted | s_shuttingDown)) { return; } if (m_pendingGroups.contains(group)) { qCDebug(DEBUGGERCOMMON) << "Already updating " << group.name(); return; } if (group.name().isEmpty()) { foreach (const GroupsName & g, namesOfRegisterGroups()) { IRegisterController::updateRegisters(g); } return; } else { qCDebug(DEBUGGERCOMMON) << "Updating: " << group.name(); m_pendingGroups << group; } QString registers; Format currentFormat = formats(group).first(); switch (currentFormat) { case Binary: registers = "t "; break; case Octal: registers = "o "; break; case Decimal : registers = "d "; break; case Hexadecimal: registers = "x "; break; case Raw: registers = "r "; break; case Unsigned: registers = "u "; break; default: break; } //float point registers have only two reasonable format. Mode currentMode = modes(group).first(); if (((currentMode >= v4_float && currentMode <= v2_double) || (currentMode >= f32 && currentMode <= f64) || group.type() == floatPoint) && currentFormat != Raw) { registers = "N "; } if (group.type() == flag) { registers += numberForName(group.flagName()); } else { foreach (const QString & name, registerNamesForGroup(group)) { registers += numberForName(name) + ' '; } } //Not initialized yet. They'll be updated afterwards. if (registers.contains("-1")) { qCDebug(DEBUGGERCOMMON) << "Will update later"; m_pendingGroups.clear(); return; } void (IRegisterController::* handler)(const ResultRecord&); if (group.type() == structured && currentFormat != Raw) { handler = &IRegisterController::structuredRegistersHandler; } else { handler = &IRegisterController::generalRegistersHandler; } m_debugSession->addCommand(DataListRegisterValues, registers, this, handler); } void IRegisterController::registerNamesHandler(const ResultRecord& r) { const Value& names = r["register-names"]; m_rawRegisterNames.clear(); for (int i = 0; i < names.size(); ++i) { const Value& entry = names[i]; m_rawRegisterNames.push_back(entry.literal()); } //When here probably request for updating registers was sent, but m_rawRegisterNames were not initialized yet, so it wasn't successful. Update everything once again. updateRegisters(); } void IRegisterController::generalRegistersHandler(const ResultRecord& r) { Q_ASSERT(!m_rawRegisterNames.isEmpty()); QString registerName; const Value& values = r["register-values"]; for (int i = 0; i < values.size(); ++i) { const Value& entry = values[i]; int number = entry["number"].literal().toInt(); Q_ASSERT(m_rawRegisterNames.size() > number); if (!m_rawRegisterNames[number].isEmpty()) { if (registerName.isEmpty()) { registerName = m_rawRegisterNames[number]; } const QString value = entry["value"].literal(); m_registers.insert(m_rawRegisterNames[number], value); } } GroupsName group = groupForRegisterName(registerName); if (m_pendingGroups.contains(group)) { emit registersChanged(registersFromGroup(group)); m_pendingGroups.remove(m_pendingGroups.indexOf(group)); } } void IRegisterController::setRegisterValue(const Register& reg) { Q_ASSERT(!m_registers.isEmpty()); const GroupsName group = groupForRegisterName(reg.name); if (!group.name().isEmpty()) { setRegisterValueForGroup(group, reg); } } QString IRegisterController::registerValue(const QString& name) const { QString value; if (!name.isEmpty()) { if (m_registers.contains(name)) { value = m_registers.value(name); } } return value; } bool IRegisterController::initializeRegisters() { if (!m_debugSession || m_debugSession->debuggerStateIsOn(s_dbgNotStarted | s_shuttingDown)) { return false; } m_debugSession->addCommand(DataListRegisterNames, "", this, &IRegisterController::registerNamesHandler); return true; } GroupsName IRegisterController::groupForRegisterName(const QString& name) const { foreach (const GroupsName & group, namesOfRegisterGroups()) { const QStringList registersInGroup = registerNamesForGroup(group); if (group.flagName() == name) { return group; } foreach (const QString & n, registersInGroup) { if (n == name) { return group; } } } return GroupsName(); } void IRegisterController::updateValuesForRegisters(RegistersGroup* registers) const { Q_ASSERT(!m_registers.isEmpty()); for (int i = 0; i < registers->registers.size(); i++) { if (m_registers.contains(registers->registers[i].name)) { registers->registers[i].value = m_registers.value(registers->registers[i].name); } } } void IRegisterController::setFlagRegister(const Register& reg, const FlagRegister& flag) { quint32 flagsValue = registerValue(flag.registerName).toUInt(nullptr, 16); const int idx = flag.flags.indexOf(reg.name); if (idx != -1) { flagsValue ^= static_cast(qPow(2, flag.bits[idx].toUInt())); setGeneralRegister(Register(flag.registerName, QString("0x%1").arg(flagsValue, 0, 16)), flag.groupName); } else { updateRegisters(flag.groupName); qCDebug(DEBUGGERCOMMON) << reg.name << ' ' << reg.value << "is incorrect flag name/value"; } } void IRegisterController::setGeneralRegister(const Register& reg, const GroupsName& group) { if (!m_debugSession || m_debugSession->debuggerStateIsOn(s_dbgNotStarted | s_shuttingDown)) { return; } const QString command = QString("set var $%1=%2").arg(reg.name).arg(reg.value); qCDebug(DEBUGGERCOMMON) << "Setting register: " << command; m_debugSession->addCommand(NonMI, command); updateRegisters(group); } IRegisterController::IRegisterController(MIDebugSession* debugSession, QObject* parent) : QObject(parent), m_debugSession(debugSession) {} IRegisterController::~IRegisterController() {} void IRegisterController::updateFlagValues(RegistersGroup* flagsGroup, const FlagRegister& flagRegister) const { const quint32 flagsValue = registerValue(flagRegister.registerName).toUInt(nullptr, 16); for (int idx = 0; idx < flagRegister.flags.count(); idx++) { flagsGroup->registers[idx].value = ((flagsValue >> flagRegister.bits[idx].toInt()) & 1) ? "1" : "0"; } } QVector IRegisterController::formats(const GroupsName& group) { int idx = -1; foreach (const GroupsName & g, namesOfRegisterGroups()) { if (g == group) { idx = g.index(); } } Q_ASSERT(idx != -1); return m_formatsModes[idx].formats; } -GroupsName IRegisterController::createGroupName(const QString& name, int idx, RegisterType t, const QString flag) const +GroupsName IRegisterController::createGroupName(const QString& name, int idx, RegisterType t, const QString& flag) const { return GroupsName(name, idx, t, flag); } void IRegisterController::setFormat(Format f, const GroupsName& group) { foreach (const GroupsName & g, namesOfRegisterGroups()) { if (g == group) { int i = m_formatsModes[g.index()].formats.indexOf(f); if (i != -1) { m_formatsModes[g.index()].formats.remove(i); m_formatsModes[g.index()].formats.prepend(f); } } } } QString IRegisterController::numberForName(const QString& name) const { //Requests for number come in order(if the previous was, let's say 10, then most likely the next one will be 11) static int previousNumber = -1; if (m_rawRegisterNames.isEmpty()) { previousNumber = -1; return QString::number(previousNumber); } if (previousNumber != -1 && m_rawRegisterNames.size() > ++previousNumber) { if (m_rawRegisterNames[previousNumber] == name) { return QString::number(previousNumber); } } for (int number = 0; number < m_rawRegisterNames.size(); number++) { if (name == m_rawRegisterNames[number]) { previousNumber = number; return QString::number(number); } } previousNumber = -1; return QString::number(previousNumber); } void IRegisterController::setStructuredRegister(const Register& reg, const GroupsName& group) { Register r = reg; r.value = r.value.trimmed(); r.value.replace(' ', ','); if (r.value.contains(',')) { r.value.append('}'); r.value.prepend('{'); } r.name += '.' + Converters::modeToString(m_formatsModes[group.index()].modes.first()); setGeneralRegister(r, group); } void IRegisterController::structuredRegistersHandler(const ResultRecord& r) { //Parsing records in format like: //{u8 = {0, 0, 128, 146, 0, 48, 197, 65}, u16 = {0, 37504, 12288, 16837}, u32 = {2457862144, 1103441920}, u64 = 4739246961893310464, f32 = {-8.07793567e-28, 24.6484375}, f64 = 710934821} //{u8 = {0 }, u16 = {0, 0, 0, 0, 0, 0, 0, 0}, u32 = {0, 0, 0, 0}, u64 = {0, 0}, f32 = {0, 0, 0, 0}, f64 = {0, 0}} QRegExp rx("^\\s*=\\s*\\{(.*)\\}"); rx.setMinimal(true); QString registerName; Mode currentMode = LAST_MODE; GroupsName group; const Value& values = r["register-values"]; Q_ASSERT(!m_rawRegisterNames.isEmpty()); for (int i = 0; i < values.size(); ++i) { const Value& entry = values[i]; int number = entry["number"].literal().toInt(); registerName = m_rawRegisterNames[number]; if (currentMode == LAST_MODE) { group = groupForRegisterName(registerName); currentMode = modes(group).first(); } QString record = entry["value"].literal(); int start = record.indexOf(Converters::modeToString(currentMode)); Q_ASSERT(start != -1); start += Converters::modeToString(currentMode).size(); QString value = record.right(record.size() - start); int idx = rx.indexIn(value); value = rx.cap(1); if (idx == -1) { //if here then value without braces: u64 = 4739246961893310464, f32 = {-8.07793567e-28, 24.6484375}, f64 = 710934821} QRegExp rx2("=\\s+(.*)(\\}|,)"); rx2.setMinimal(true); rx2.indexIn(record, start); value = rx2.cap(1); } value = value.trimmed().remove(','); m_registers.insert(registerName, value); } if (m_pendingGroups.contains(group)) { emit registersChanged(registersFromGroup(group)); m_pendingGroups.remove(m_pendingGroups.indexOf(group)); } } QVector< Mode > IRegisterController::modes(const GroupsName& group) { int idx = -1; foreach (const GroupsName & g, namesOfRegisterGroups()) { if (g == group) { idx = g.index(); } } Q_ASSERT(idx != -1); return m_formatsModes[idx].modes; } void IRegisterController::setMode(Mode m, const GroupsName& group) { foreach (const GroupsName & g, namesOfRegisterGroups()) { if (g == group) { int i = m_formatsModes[g.index()].modes.indexOf(m); if (i != -1) { m_formatsModes[g.index()].modes.remove(i); m_formatsModes[g.index()].modes.prepend(m); } } } } diff --git a/debuggers/common/registers/registercontroller.h b/debuggers/common/registers/registercontroller.h index 7de34b5dcc..cd03bff30c 100644 --- a/debuggers/common/registers/registercontroller.h +++ b/debuggers/common/registers/registercontroller.h @@ -1,247 +1,247 @@ /* * Class to fetch/change/send registers to the debugger. * Copyright 2013 Vlas Puhov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */ #ifndef _REGISTERCONTROLLER_H_ #define _REGISTERCONTROLLER_H_ #include #include #include #include #include namespace KDevMI { namespace MI { struct ResultRecord; } class MIDebugSession; enum RegisterType {general, structured, flag, floatPoint}; class GroupsName { public: QString name() const { return _name;} int index() const {return _index;} RegisterType type() const{return _type; } QString flagName() const{return _flagName;} bool operator==(const GroupsName& g) const {return _name == g.name();} GroupsName(): _index(-1), _type(general) {} private: - GroupsName(const QString& name, int idx, RegisterType type = general, const QString flag = QString()): _name(name), _index(idx), _type(type), _flagName(flag) {} + GroupsName(const QString& name, int idx, RegisterType type = general, const QString& flag = QString()): _name(name), _index(idx), _type(type), _flagName(flag) {} private: QString _name; int _index; ///Should be unique for each group for current architecture (0, 1...n). RegisterType _type; QString _flagName; ///Used only for flag registers. friend class IRegisterController; friend struct RegistersGroup; }; enum Format { Binary, Octal, Decimal, Hexadecimal, Raw, Unsigned, LAST_FORMAT }; enum Mode { natural, v4_float, v2_double, v4_int32, v2_int64, u32, u64, f32, f64, LAST_MODE }; struct FormatsModes { QVector formats; QVector modes; }; ///Register in format: @p name, @p value - space separated list of values struct Register { Register() {} Register(const QString& _name, const QString& _value): name(_name), value(_value) {} QString name; QString value; }; ///List of @p registers for @p groupName in @p format struct RegistersGroup { RegistersGroup() : format(Binary) , flag(false) {} GroupsName groupName; QVector registers; Format format; /// namesOfRegisterGroups() const = 0; ///Returns all supported formats for @p group (bin, dec, hex ...) QVector formats(const GroupsName& group); ///Sets current format for the @p group, if format is supported. Does nothing otherwise. void setFormat(Format f, const GroupsName& group); ///Returns all supported modes for @p group (i.e. how to display group: 2 int, 4 float or other number of columns) QVector modes(const GroupsName& group); ///Sets current mode for the @p group, if mode is supported. Does nothing otherwise. void setMode(Mode m, const GroupsName& group); signals: ///Emits @p group with updated registers. void registersChanged(const RegistersGroup& g); public slots: ///Updates registers in @p group. If @p group is empty - updates all registers. virtual void updateRegisters(const GroupsName& group = GroupsName()); ///Sends updated register's @p reg value to the debugger. virtual void setRegisterValue(const Register& reg); protected: explicit IRegisterController(MIDebugSession* debugSession = nullptr, QObject* parent = nullptr); ///Returns registers from the @p group, or empty registers group if @p group is invalid. virtual RegistersGroup registersFromGroup(const GroupsName& group) const = 0; ///Sets value for @p register from @p group. virtual void setRegisterValueForGroup(const GroupsName& group, const Register& reg) = 0; ///Returns names of all registers for @p group. virtual QStringList registerNamesForGroup(const GroupsName& group) const = 0; /**Updates value for each register in the group. * @param [out] registers Registers which values should be updated. */ virtual void updateValuesForRegisters(RegistersGroup* registers) const; ///Returns value for the given @p name, empty string if the name is incorrect or there is no registers yet. QString registerValue(const QString& name) const; /** Sets a flag register. * @param reg register to set * @param flag flag register @p reg belongs to. */ void setFlagRegister(const Register& reg, const FlagRegister& flag); ///Sets new value for register @p reg, from group @p group. void setGeneralRegister(const Register& reg, const GroupsName& group); ///Sets new value for structured register(XMM, VFP quad and other) @p reg, from group @p group. void setStructuredRegister(const Register& reg, const GroupsName& group); ///Updates values in @p flagsGroup for @p flagRegister. void updateFlagValues(RegistersGroup* flagsGroup, const FlagRegister& flagRegister) const; ///Returns group that given register belongs to. GroupsName groupForRegisterName(const QString& name) const; ///Initializes registers, that is gets names of all available registers. Returns true is succeed. bool initializeRegisters(); - GroupsName createGroupName(const QString& name, int idx, RegisterType t = general, const QString flag = QString()) const; + GroupsName createGroupName(const QString& name, int idx, RegisterType t = general, const QString& flag = QString()) const; ///Returns register's number for @p name. QString numberForName(const QString& name) const; public: ~IRegisterController() override; private : ///Handles initialization of register's names. void registerNamesHandler(const MI::ResultRecord& r); ///Parses new values for general registers from @p r and updates it in m_registers. ///Emits registersChanged signal. void generalRegistersHandler(const MI::ResultRecord& r); ///Parses new values for structured registers from @p r and updates it in m_registers. ///Emits registersChanged signal. virtual void structuredRegistersHandler(const MI::ResultRecord& r); private: ///Groups that should be updated(emitted @p registersInGroupChanged signal), if empty - all. QVector m_pendingGroups; protected: ///Register names as it sees debugger (in format: number, name). QVector m_rawRegisterNames; ///Registers in format: name, value QHash m_registers; ///Supported formats and modes for each register's group. First format/mode is current. QVector m_formatsModes; ///Current debug session; MIDebugSession* m_debugSession; }; } // end of namespace KDevMI Q_DECLARE_TYPEINFO(KDevMI::Register, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(KDevMI::RegistersGroup, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(KDevMI::FlagRegister, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(KDevMI::GroupsName, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(KDevMI::FormatsModes, Q_MOVABLE_TYPE); #endif diff --git a/projectmanagers/cmake/parser/cmakeduchaintypes.cpp b/projectmanagers/cmake/parser/cmakeduchaintypes.cpp index 69830ad13d..bfbb29d3fd 100644 --- a/projectmanagers/cmake/parser/cmakeduchaintypes.cpp +++ b/projectmanagers/cmake/parser/cmakeduchaintypes.cpp @@ -1,51 +1,51 @@ /* KDevelop CMake Support * * Copyright 2007-2012 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "cmakeduchaintypes.h" #include namespace KDevelop { REGISTER_TYPE(TargetType); } TargetType::TargetType() : AbstractType(createData()) {} -TargetType::TargetType(TargetType& rhs) +TargetType::TargetType(const TargetType& rhs) : AbstractType(copyData(*rhs.d_func())) {} TargetType::TargetType(KDevelop::AbstractTypeData& dd): AbstractType(dd) {} KDevelop::AbstractType* TargetType::clone() const { return new TargetType; } void TargetType::accept0(KDevelop::TypeVisitor* ) const {} bool TargetType::equals(const KDevelop::AbstractType* rhs) const { return dynamic_cast(rhs)!=nullptr; } diff --git a/projectmanagers/cmake/parser/cmakeduchaintypes.h b/projectmanagers/cmake/parser/cmakeduchaintypes.h index 3cd201246a..9e5c7290e1 100644 --- a/projectmanagers/cmake/parser/cmakeduchaintypes.h +++ b/projectmanagers/cmake/parser/cmakeduchaintypes.h @@ -1,50 +1,50 @@ /* KDevelop CMake Support * * Copyright 2007-2012 Aleix Pol * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef CMAKEDUCHAINTYPES_H #define CMAKEDUCHAINTYPES_H #include #include #include "cmaketypes.h" struct KDEVCMAKECOMMON_EXPORT TargetTypeData : public KDevelop::AbstractTypeData { TargetTypeData() {} ~TargetTypeData() {} TargetTypeData(const TargetTypeData& rhs) : AbstractTypeData(rhs) {} }; class KDEVCMAKECOMMON_EXPORT TargetType : public KDevelop::AbstractType { public: TargetType(); - TargetType(TargetType& rhs); + TargetType(const TargetType& rhs); explicit TargetType(KDevelop::AbstractTypeData& dd); void accept0(KDevelop::TypeVisitor* v) const override; AbstractType* clone() const override; bool equals(const AbstractType* rhs) const override; private: TYPE_DECLARE_DATA(TargetType) }; #endif