Browse Source

HackStudio: Support debugging variables with Enum types

Variables with enum types can now be both viewed and modified in the
variables view!
FalseHonesty 5 years ago
parent
commit
f958c693ee

+ 6 - 0
Base/home/anon/little/main.cpp

@@ -1,9 +1,15 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
 
 
+enum TestEnum {
+    ValueOne,
+    ValueTwo
+};
+
 struct MyStruct {
 struct MyStruct {
     int x { -1 };
     int x { -1 };
     bool status { false };
     bool status { false };
+    TestEnum test_value { ValueOne };
 };
 };
 
 
 int main(int, char**)
 int main(int, char**)

+ 1 - 1
DevTools/HackStudio/Debugger/DebugInfoWidget.cpp

@@ -71,7 +71,7 @@ DebugInfoWidget::DebugInfoWidget()
         auto* variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
         auto* variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
         if (variable->location_type != DebugInfo::VariableInfo::LocationType::Address)
         if (variable->location_type != DebugInfo::VariableInfo::LocationType::Address)
             return false;
             return false;
-        return variable->type.is_one_of("int", "bool");
+        return variable->is_enum_type() || variable->type_name.is_one_of("int", "bool");
     };
     };
 
 
     m_variables_view->on_context_menu_request = [this, is_valid_index](auto& index, auto& event) {
     m_variables_view->on_context_menu_request = [this, is_valid_index](auto& index, auto& event) {

+ 34 - 9
DevTools/HackStudio/Debugger/VariablesModel.cpp

@@ -75,36 +75,61 @@ String variable_value_as_string(const DebugInfo::VariableInfo& variable)
 
 
     auto variable_address = variable.location_data.address;
     auto variable_address = variable.location_data.address;
 
 
-    if (variable.type == "int") {
+    if (variable.is_enum_type()) {
+        auto value = Debugger::the().session()->peek((u32*)variable_address);
+        ASSERT(value.has_value());
+        auto it = variable.type->members.find([enumerator_value = value.value()](auto& enumerator) {
+            return enumerator->constant_data.as_u32 == enumerator_value;
+        });
+        ASSERT(!it.is_end());
+        return String::format("%s::%s", variable.type_name.characters(), (*it)->name.characters());
+    }
+
+    if (variable.type_name == "int") {
         auto value = Debugger::the().session()->peek((u32*)variable_address);
         auto value = Debugger::the().session()->peek((u32*)variable_address);
         ASSERT(value.has_value());
         ASSERT(value.has_value());
         return String::format("%d", static_cast<int>(value.value()));
         return String::format("%d", static_cast<int>(value.value()));
     }
     }
 
 
-    if (variable.type == "char") {
+    if (variable.type_name == "char") {
         auto value = Debugger::the().session()->peek((u32*)variable_address);
         auto value = Debugger::the().session()->peek((u32*)variable_address);
         ASSERT(value.has_value());
         ASSERT(value.has_value());
         return String::format("'%c' (%d)", static_cast<char>(value.value()), static_cast<char>(value.value()));
         return String::format("'%c' (%d)", static_cast<char>(value.value()), static_cast<char>(value.value()));
     }
     }
 
 
-    if (variable.type == "bool") {
+    if (variable.type_name == "bool") {
         auto value = Debugger::the().session()->peek((u32*)variable_address);
         auto value = Debugger::the().session()->peek((u32*)variable_address);
         ASSERT(value.has_value());
         ASSERT(value.has_value());
         return (value.value() & 1) ? "true" : "false";
         return (value.value() & 1) ? "true" : "false";
     }
     }
 
 
-    return String::format("type: %s @ %08x, ", variable.type.characters(), variable_address);
+    return String::format("type: %s @ %08x, ", variable.type_name.characters(), variable_address);
 }
 }
 
 
-static Optional<u32> string_to_value_of_type(const StringView& string_value, const StringView& type)
+static Optional<u32> string_to_variable_value(const StringView& string_value, const DebugInfo::VariableInfo& variable)
 {
 {
-    if (type == "int") {
+    if (variable.is_enum_type()) {
+        auto prefix_string = String::format("%s::", variable.type_name.characters());
+        auto string_to_use = string_value;
+        if (string_value.starts_with(prefix_string))
+            string_to_use = string_value.substring_view(prefix_string.length(), string_value.length() - prefix_string.length());
+
+        auto it = variable.type->members.find([string_to_use](auto& enumerator) {
+            return enumerator->name == string_to_use;
+        });
+
+        if (it.is_end())
+            return {};
+        return (*it)->constant_data.as_u32;
+    }
+
+    if (variable.type_name == "int") {
         bool success = false;
         bool success = false;
         auto value = string_value.to_int(success);
         auto value = string_value.to_int(success);
         return success ? value : Optional<u32>();
         return success ? value : Optional<u32>();
     }
     }
 
 
-    if (type == "bool") {
+    if (variable.type_name == "bool") {
         if (string_value == "true")
         if (string_value == "true")
             return true;
             return true;
         if (string_value == "false")
         if (string_value == "false")
@@ -119,7 +144,7 @@ void VariablesModel::set_variable_value(const GUI::ModelIndex& index, const Stri
 {
 {
     auto variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
     auto variable = static_cast<const DebugInfo::VariableInfo*>(index.internal_data());
 
 
-    auto value = string_to_value_of_type(string_value, variable->type);
+    auto value = string_to_variable_value(string_value, *variable);
 
 
     if (value.has_value()) {
     if (value.has_value()) {
         auto success = Debugger::the().session()->poke((u32*)variable->location_data.address, value.value());
         auto success = Debugger::the().session()->poke((u32*)variable->location_data.address, value.value());
@@ -128,7 +153,7 @@ void VariablesModel::set_variable_value(const GUI::ModelIndex& index, const Stri
     }
     }
 
 
     GUI::MessageBox::show(
     GUI::MessageBox::show(
-        String::format("String value \"%s\" could not be converted to a value of type %s.", string_value.to_string().characters(), variable->type.characters()),
+        String::format("String value \"%s\" could not be converted to a value of type %s.", string_value.to_string().characters(), variable->type_name.characters()),
         "Set value failed",
         "Set value failed",
         GUI::MessageBox::Type::Error,
         GUI::MessageBox::Type::Error,
         GUI::MessageBox::InputType::OK,
         GUI::MessageBox::InputType::OK,