From 31b0772137efe5426e5ffa0fee27eb63a85e5d93 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Fri, 7 Feb 2025 09:21:06 -0800 Subject: [PATCH] eval viz: view rule -> expansion rule; rd: view rule -> view ui rule --- src/eval/eval_bundles.c | 13 + src/eval/eval_bundles.h | 1 + src/eval/eval_parse.h | 2 +- .../eval_visualization_core.h | 5 +- src/raddbg/generated/raddbg.meta.c | 17 - src/raddbg/generated/raddbg.meta.h | 51 -- src/raddbg/raddbg.mdesk | 2 + src/raddbg/raddbg_core.c | 601 +++++++++++++++--- src/raddbg/raddbg_core.h | 75 ++- src/raddbg/raddbg_views.c | 389 +----------- src/raddbg/raddbg_views.h | 15 + 11 files changed, 659 insertions(+), 512 deletions(-) diff --git a/src/eval/eval_bundles.c b/src/eval/eval_bundles.c index db040024..6d966dea 100644 --- a/src/eval/eval_bundles.c +++ b/src/eval/eval_bundles.c @@ -40,6 +40,19 @@ e_eval_from_string(Arena *arena, String8 string) return eval; } +internal E_Eval +e_eval_from_stringf(Arena *arena, char *fmt, ...) +{ + Temp scratch = scratch_begin(&arena, 1); + va_list args; + va_start(args, fmt); + String8 string = push_str8fv(scratch.arena, fmt, args); + E_Eval eval = e_eval_from_string(arena, string); + va_end(args); + scratch_end(scratch); + return eval; +} + internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval) { diff --git a/src/eval/eval_bundles.h b/src/eval/eval_bundles.h index 957ff123..f835a6cb 100644 --- a/src/eval/eval_bundles.h +++ b/src/eval/eval_bundles.h @@ -24,6 +24,7 @@ struct E_Eval internal E_Eval e_eval_from_expr(Arena *arena, E_Expr *expr); internal E_Eval e_eval_from_string(Arena *arena, String8 string); +internal E_Eval e_eval_from_stringf(Arena *arena, char *fmt, ...); internal E_Eval e_autoresolved_eval_from_eval(E_Eval eval); internal E_Eval e_dynamically_typed_eval_from_eval(E_Eval eval); internal E_Eval e_value_eval_from_eval(E_Eval eval); diff --git a/src/eval/eval_parse.h b/src/eval/eval_parse.h index d91a2c76..7e0fcaf6 100644 --- a/src/eval/eval_parse.h +++ b/src/eval/eval_parse.h @@ -214,7 +214,7 @@ struct E_ParseState global read_only E_String2NumMap e_string2num_map_nil = {0}; global read_only E_String2ExprMap e_string2expr_map_nil = {0}; -global read_only E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil}; +global read_only E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil}; thread_static E_ParseState *e_parse_state = 0; //////////////////////////////// diff --git a/src/eval_visualization/eval_visualization_core.h b/src/eval_visualization/eval_visualization_core.h index b9651404..14548ec9 100644 --- a/src/eval_visualization/eval_visualization_core.h +++ b/src/eval_visualization/eval_visualization_core.h @@ -75,7 +75,7 @@ struct EV_View }; //////////////////////////////// -//~ rjf: View Rule Info Types +//~ rjf: Expansion Rule Types typedef struct EV_ExpandInfo EV_ExpandInfo; struct EV_ExpandInfo @@ -120,9 +120,6 @@ struct EV_ExpandRuleTable U64 slots_count; }; -//////////////////////////////// -//~ rjf: Expansion Rule Types - typedef struct EV_ExpandRuleTagPair EV_ExpandRuleTagPair; struct EV_ExpandRuleTagPair { diff --git a/src/raddbg/generated/raddbg.meta.c b/src/raddbg/generated/raddbg.meta.c index 7d2b7370..b20c50db 100644 --- a/src/raddbg/generated/raddbg.meta.c +++ b/src/raddbg/generated/raddbg.meta.c @@ -562,23 +562,6 @@ str8_lit_comp("5"), str8_lit_comp("c"), }; -RD_ViewRuleInfo rd_view_rule_kind_info_table[13] = -{ -{{0}, {0}, {0}, {0}, RD_IconKind_Null, 0, EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(null)}, -{str8_lit_comp("empty"), str8_lit_comp(""), str8_lit_comp(""), str8_lit_comp(""), RD_IconKind_Null, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(empty)}, -{str8_lit_comp("getting_started"), str8_lit_comp(""), str8_lit_comp("Getting Started"), str8_lit_comp(""), RD_IconKind_QuestionMark, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(getting_started)}, -{str8_lit_comp("settings"), str8_lit_comp("An interface to modify general settings for the debugger's appearance and behavior."), str8_lit_comp("Settings"), str8_lit_comp(""), RD_IconKind_Gear, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(settings)}, -{str8_lit_comp("pending_file"), str8_lit_comp(""), str8_lit_comp("Pending File"), str8_lit_comp(""), RD_IconKind_FileOutline, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(pending_file)}, -{str8_lit_comp("watch"), str8_lit_comp("The familiar 'watch window' debugger interface. Allows the inputting of a number of expressions. Each expression in the table is evaluated within the context of the selected thread's selected call stack frame. If applicable (depending on visualization rules and the expression's type), these expressions may be hierarchically expanded, which displays children as more rows in the table. The values of these expressions may also be edited, and if possible, can be used to write to registers or memory in attached processes. Also contains a new *view rule* column, not found in other major debuggers, which allows per-row specification of various visualization rules. These view rules may be used to visualize and inspect the evaluation of expressions in a variety of ways. To learn more, read the 'View Rules' section."), str8_lit_comp("Watch"), str8_lit_comp(""), RD_IconKind_Binoculars, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*1|RD_ViewRuleInfoFlag_FilterIsCode*1|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*1|RD_ViewRuleInfoFlag_CanUseInWatchTable*0|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*0), EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(watch)}, -{str8_lit_comp("text"), str8_lit_comp(""), str8_lit_comp("Text"), str8_lit_comp("x:{'lang':lang, 'size':expr}"), RD_IconKind_FileOutline, (RD_ViewRuleInfoFlag_ShowInDocs*0|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*1|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*1), EV_EXPAND_RULE_INFO_FUNCTION_NAME(text) , RD_VIEW_RULE_UI_FUNCTION_NAME(text)}, -{str8_lit_comp("disasm"), str8_lit_comp("Displays disassembled instructions in a textual form from the selected thread's containing process virtual address space."), str8_lit_comp("Disassembly"), str8_lit_comp("x:{'arch':arch, 'size':expr, 'addresses':bool, 'code_bytes':bool}"), RD_IconKind_Glasses, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*1|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*1), EV_EXPAND_RULE_INFO_FUNCTION_NAME(disasm) , RD_VIEW_RULE_UI_FUNCTION_NAME(disasm)}, -{str8_lit_comp("memory"), str8_lit_comp("A hex-editor-like grid interface for viewing memory."), str8_lit_comp("Memory"), str8_lit_comp("x:{'size':expr}"), RD_IconKind_Grid, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*1|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*1), EV_EXPAND_RULE_INFO_FUNCTION_NAME(memory) , RD_VIEW_RULE_UI_FUNCTION_NAME(memory)}, -{str8_lit_comp("bitmap"), str8_lit_comp("Visualizes memory as a bitmap."), str8_lit_comp("Bitmap"), str8_lit_comp("x:{'w':expr, 'h':expr, 'fmt':tex2dformat}"), RD_IconKind_Binoculars, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*1|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*1), EV_EXPAND_RULE_INFO_FUNCTION_NAME(bitmap) , RD_VIEW_RULE_UI_FUNCTION_NAME(bitmap)}, -{str8_lit_comp("checkbox"), str8_lit_comp("Visualizes memory as an RGBA color."), str8_lit_comp("Checkbox"), str8_lit_comp(""), RD_IconKind_CheckFilled, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*1|RD_ViewRuleInfoFlag_CanFillValueCell*1|RD_ViewRuleInfoFlag_CanExpand*0), EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(checkbox)}, -{str8_lit_comp("color_rgba"), str8_lit_comp("Visualizes memory as an RGBA color."), str8_lit_comp("Color (RGBA)"), str8_lit_comp(""), RD_IconKind_Palette, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*1|RD_ViewRuleInfoFlag_CanFillValueCell*1|RD_ViewRuleInfoFlag_CanExpand*1), EV_EXPAND_RULE_INFO_FUNCTION_NAME(color_rgba) , RD_VIEW_RULE_UI_FUNCTION_NAME(color_rgba)}, -{str8_lit_comp("geo3d"), str8_lit_comp("Visualizes memory as 3D geometry."), str8_lit_comp("Geometry (3D)"), str8_lit_comp("x:{'count':expr, 'vtx':expr, 'vtx_size':expr}"), RD_IconKind_Binoculars, (RD_ViewRuleInfoFlag_ShowInDocs*1|RD_ViewRuleInfoFlag_CanFilter*0|RD_ViewRuleInfoFlag_FilterIsCode*0|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*0|RD_ViewRuleInfoFlag_CanUseInWatchTable*1|RD_ViewRuleInfoFlag_CanFillValueCell*0|RD_ViewRuleInfoFlag_CanExpand*1), EV_EXPAND_RULE_INFO_FUNCTION_NAME(geo3d) , RD_VIEW_RULE_UI_FUNCTION_NAME(geo3d)}, -}; - String8 rd_theme_preset_display_string_table[9] = { str8_lit_comp("Default (Dark)"), diff --git a/src/raddbg/generated/raddbg.meta.h b/src/raddbg/generated/raddbg.meta.h index 21abb11c..7de4f395 100644 --- a/src/raddbg/generated/raddbg.meta.h +++ b/src/raddbg/generated/raddbg.meta.h @@ -350,24 +350,6 @@ RD_IconKind_Dot, RD_IconKind_COUNT, } RD_IconKind; -typedef enum RD_ViewRuleKind -{ -RD_ViewRuleKind_Null, -RD_ViewRuleKind_Empty, -RD_ViewRuleKind_GettingStarted, -RD_ViewRuleKind_Settings, -RD_ViewRuleKind_PendingFile, -RD_ViewRuleKind_Watch, -RD_ViewRuleKind_Text, -RD_ViewRuleKind_Disasm, -RD_ViewRuleKind_Memory, -RD_ViewRuleKind_Bitmap, -RD_ViewRuleKind_Checkbox, -RD_ViewRuleKind_ColorRGBA, -RD_ViewRuleKind_Geo3D, -RD_ViewRuleKind_COUNT, -} RD_ViewRuleKind; - typedef enum RD_ThemeColor { RD_ThemeColor_Null, @@ -545,19 +527,6 @@ RD_CmdKindFlags flags; RD_Query query; }; -typedef struct RD_ViewRuleInfo RD_ViewRuleInfo; -struct RD_ViewRuleInfo -{ -String8 string; -String8 description; -String8 display_name; -String8 params_schema; -RD_IconKind icon_kind; -RD_ViewRuleInfoFlags flags; -EV_ExpandRuleInfoHookFunctionType *expr_expand_info; -RD_ViewRuleUIFunctionType *ui; -}; - #define rd_regs_lit_init_top \ .machine = rd_regs()->machine,\ .module = rd_regs()->module,\ @@ -597,25 +566,6 @@ RD_ViewRuleUIFunctionType *ui; .params_tree = rd_regs()->params_tree,\ .os_event = rd_regs()->os_event,\ -RD_VIEW_RULE_UI_FUNCTION_DEF(null); -EV_EXPAND_RULE_INFO_FUNCTION_DEF(text); -EV_EXPAND_RULE_INFO_FUNCTION_DEF(disasm); -EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory); -EV_EXPAND_RULE_INFO_FUNCTION_DEF(bitmap); -EV_EXPAND_RULE_INFO_FUNCTION_DEF(color_rgba); -EV_EXPAND_RULE_INFO_FUNCTION_DEF(geo3d); -RD_VIEW_RULE_UI_FUNCTION_DEF(empty); -RD_VIEW_RULE_UI_FUNCTION_DEF(getting_started); -RD_VIEW_RULE_UI_FUNCTION_DEF(settings); -RD_VIEW_RULE_UI_FUNCTION_DEF(pending_file); -RD_VIEW_RULE_UI_FUNCTION_DEF(watch); -RD_VIEW_RULE_UI_FUNCTION_DEF(text); -RD_VIEW_RULE_UI_FUNCTION_DEF(disasm); -RD_VIEW_RULE_UI_FUNCTION_DEF(memory); -RD_VIEW_RULE_UI_FUNCTION_DEF(bitmap); -RD_VIEW_RULE_UI_FUNCTION_DEF(checkbox); -RD_VIEW_RULE_UI_FUNCTION_DEF(color_rgba); -RD_VIEW_RULE_UI_FUNCTION_DEF(geo3d); C_LINKAGE_BEGIN extern String8 rd_cfg_src_string_table[4]; extern RD_CmdKind rd_cfg_src_load_cmd_kind_table[4]; @@ -627,7 +577,6 @@ extern RD_StringBindingPair rd_default_binding_table[111]; extern String8 rd_binding_version_remap_old_name_table[8]; extern String8 rd_binding_version_remap_new_name_table[8]; extern String8 rd_icon_kind_text_table[69]; -extern RD_ViewRuleInfo rd_view_rule_kind_info_table[13]; extern String8 rd_theme_preset_display_string_table[9]; extern String8 rd_theme_preset_code_string_table[9]; extern String8 rd_theme_color_version_remap_old_name_table[22]; diff --git a/src/raddbg/raddbg.mdesk b/src/raddbg/raddbg.mdesk index d8aaf044..ec0bf8a1 100644 --- a/src/raddbg/raddbg.mdesk +++ b/src/raddbg/raddbg.mdesk @@ -945,6 +945,7 @@ RD_ViewRuleTable: { Geo3D geo3d "Geometry (3D)" "x:{'count':expr, 'vtx':expr, 'vtx_size':expr}" Binoculars 0 0 0 1 0 1 1 "Visualizes memory as 3D geometry." } } +/* @enum RD_ViewRuleKind: { Null, @@ -976,6 +977,7 @@ RD_ViewRuleTable: `{{0}, {0}, {0}, {0}, RD_IconKind_Null, 0, EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(null)}`, @expand(RD_ViewRuleTable a) `{str8_lit_comp("$(a.name_lower)"), str8_lit_comp("$(a.description)"), str8_lit_comp("$(a.display_name)"), str8_lit_comp("$(a.params_schema)"), RD_IconKind_$(a.icon), (RD_ViewRuleInfoFlag_ShowInDocs*$(a.show_in_docs)|RD_ViewRuleInfoFlag_CanFilter*$(a.can_filter)|RD_ViewRuleInfoFlag_FilterIsCode*$(a.filter_is_code)|RD_ViewRuleInfoFlag_TypingAutomaticallyFilters*$(a.typing_automatically_filters)|RD_ViewRuleInfoFlag_CanUseInWatchTable*$(a.can_use_in_watch_table)|RD_ViewRuleInfoFlag_CanFillValueCell*$(a.can_fill_value_cell)|RD_ViewRuleInfoFlag_CanExpand*$(a.can_expand)), $(a.can_expand != 0 -> "EV_EXPAND_RULE_INFO_FUNCTION_NAME(" .. a.name_lower .. ")") $(a.can_expand == 0 -> "EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil)"), RD_VIEW_RULE_UI_FUNCTION_NAME($(a.name_lower))}`, } +*/ //////////////////////////////// //~ rjf: Theme Tables diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 4ae3f566..f9c6a537 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -76,6 +76,7 @@ rd_cmd_list_push_new(Arena *arena, RD_CmdList *cmds, String8 name, RD_Regs *regs //////////////////////////////// //~ rjf: View Spec Type Functions +#if 0 // TODO(rjf): @cfg internal RD_ViewRuleKind rd_view_rule_kind_from_string(String8 string) { @@ -110,6 +111,50 @@ rd_view_rule_info_from_string(String8 string) } return result; } +#endif + +//////////////////////////////// +//~ rjf: View UI Rule Functions + +internal RD_ViewUIRuleMap * +rd_view_ui_rule_map_make(Arena *arena, U64 slots_count) +{ + RD_ViewUIRuleMap *map = push_array(arena, RD_ViewUIRuleMap, 1); + map->slots_count = slots_count; + map->slots = push_array(arena, RD_ViewUIRuleSlot, map->slots_count); + return map; +} + +internal void +rd_view_ui_rule_map_insert(Arena *arena, RD_ViewUIRuleMap *map, String8 string, RD_ViewUIFunctionType *ui) +{ + U64 hash = d_hash_from_string(string); + U64 slot_idx = hash%map->slots_count; + RD_ViewUIRuleNode *n = push_array(arena, RD_ViewUIRuleNode, 1); + n->v.name = push_str8_copy(arena, string); + n->v.ui = ui; + SLLQueuePush(map->slots[slot_idx].first, map->slots[slot_idx].last, n); +} + +internal RD_ViewUIRule * +rd_view_ui_rule_from_string(String8 string) +{ + RD_ViewUIRule *rule = &rd_nil_view_ui_rule; + { + RD_ViewUIRuleMap *map = rd_state->view_ui_rule_map; + U64 hash = d_hash_from_string(string); + U64 slot_idx = hash%map->slots_count; + for(RD_ViewUIRuleNode *n = map->slots[slot_idx].first; n != 0; n = n->next) + { + if(str8_match(n->v.name, string, 0)) + { + rule = &n->v; + break; + } + } + } + return rule; +} //////////////////////////////// //~ rjf: Global Cross-Window UI Interaction State Functions @@ -1533,6 +1578,16 @@ rd_possible_overrides_from_file_path(Arena *arena, String8 file_path) return result; } +internal E_Expr * +rd_tag_from_cfg(Arena *arena, RD_Cfg *cfg) +{ + E_Expr *expr = &e_expr_nil; + { + // TODO(rjf): @cfg + } + return expr; +} + //////////////////////////////// //~ rjf: Control Entity Info Extraction @@ -2410,16 +2465,6 @@ rd_commit_eval_value_string(E_Eval dst_eval, String8 string, B32 string_needs_un //- rjf: view rule config tree info extraction -internal U64 -rd_base_offset_from_eval(E_Eval eval) -{ - if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(eval.type_key))) - { - eval = e_value_eval_from_eval(eval); - } - return eval.value.u64; -} - internal E_Value rd_value_from_params_key(MD_Node *params, String8 key) { @@ -2739,6 +2784,272 @@ rd_title_fstrs_from_view(Arena *arena, String8 viewer_name_string, String8 query return result; } +internal void +rd_view_ui(Rng2F32 rect) +{ + ProfBeginFunction(); + RD_Cfg *view = rd_cfg_from_id(rd_regs()->view); + String8 view_name = view->string; + String8 expr_string = rd_expr_from_cfg(view); + + ////////////////////////////// + //- rjf: special-case view: "getting started" + // + if(0){} + else if(str8_match(view_name, str8_lit("getting_started"), 0)) + { + Temp scratch = scratch_begin(0, 0); + ui_set_next_flags(UI_BoxFlag_DefaultFocusNav); + UI_Focus(UI_FocusKind_On) UI_WidthFill UI_HeightFill UI_NamedColumn(str8_lit("empty_view")) + UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) + UI_Padding(ui_pct(1, 0)) UI_Focus(UI_FocusKind_Null) + { + RD_CfgList targets = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("target")); + CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process); + + //- rjf: icon & info + UI_Padding(ui_em(2.f, 1.f)) + { + //- rjf: icon + { + F32 icon_dim = ui_top_font_size()*10.f; + UI_PrefHeight(ui_px(icon_dim, 1.f)) + UI_Row + UI_Padding(ui_pct(1, 0)) + UI_PrefWidth(ui_px(icon_dim, 1.f)) + { + R_Handle texture = rd_state->icon_texture; + Vec2S32 texture_dim = r_size_from_tex2d(texture); + ui_image(texture, R_Tex2DSampleKind_Linear, r2f32p(0, 0, texture_dim.x, texture_dim.y), v4f32(1, 1, 1, 1), 0, str8_lit("")); + } + } + + //- rjf: info + UI_Padding(ui_em(2.f, 1.f)) + UI_WidthFill UI_PrefHeight(ui_em(2.f, 1.f)) + UI_Row + UI_Padding(ui_pct(1, 0)) + UI_TextAlignment(UI_TextAlign_Center) + UI_PrefWidth(ui_text_dim(10, 1)) + { + ui_label(str8_lit(BUILD_TITLE_STRING_LITERAL)); + } + } + + //- rjf: targets state dependent helper + B32 helper_built = 0; + if(processes.count == 0) + { + helper_built = 1; + switch(targets.count) + { + //- rjf: user has no targets. build helper for adding them + case 0: + { + UI_PrefHeight(ui_em(3.75f, 1.f)) + UI_Row + UI_Padding(ui_pct(1, 0)) + UI_TextAlignment(UI_TextAlign_Center) + UI_PrefWidth(ui_em(22.f, 1.f)) + UI_CornerRadius(ui_top_font_size()/2.f) + RD_Palette(RD_PaletteCode_NeutralPopButton) + if(ui_clicked(rd_icon_buttonf(RD_IconKind_Add, 0, "Add Target"))) + { + rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_AddTarget].string); + } + }break; + + //- rjf: user has 1 target. build helper for launching it + case 1: + { + RD_Cfg *target_cfg = rd_cfg_list_first(&targets); + D_Target target = rd_target_from_cfg(scratch.arena, target_cfg); + String8 target_full_path = target.exe; + String8 target_name = str8_skip_last_slash(target_full_path); + UI_PrefHeight(ui_em(3.75f, 1.f)) + UI_Row + UI_Padding(ui_pct(1, 0)) + UI_TextAlignment(UI_TextAlign_Center) + UI_PrefWidth(ui_em(22.f, 1.f)) + UI_CornerRadius(ui_top_font_size()/2.f) + RD_Palette(RD_PaletteCode_PositivePopButton) + { + if(ui_clicked(rd_icon_buttonf(RD_IconKind_Play, 0, "Launch %S", target_name))) + { + rd_cmd(RD_CmdKind_LaunchAndRun, .cfg = target_cfg->id); + } + ui_spacer(ui_em(1.5f, 1)); + if(ui_clicked(rd_icon_buttonf(RD_IconKind_Play, 0, "Step Into %S", target_name))) + { + rd_cmd(RD_CmdKind_LaunchAndInit, .cfg = target_cfg->id); + } + } + }break; + + //- rjf: user has N targets. + default: + { + helper_built = 0; + }break; + } + } + + //- rjf: or text + if(helper_built) + { + UI_PrefHeight(ui_em(2.25f, 1.f)) + UI_Row + UI_Padding(ui_pct(1, 0)) + UI_TextAlignment(UI_TextAlign_Center) + UI_WidthFill + ui_labelf("- or -"); + } + + //- rjf: helper text for command lister activation + UI_PrefHeight(ui_em(2.25f, 1.f)) UI_Row + UI_PrefWidth(ui_text_dim(10, 1)) + UI_TextAlignment(UI_TextAlign_Center) + UI_Padding(ui_pct(1, 0)) + RD_Palette(RD_PaletteCode_Floating) + { + ui_labelf("use"); + UI_TextAlignment(UI_TextAlign_Center) rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_OpenLister].string); + ui_labelf("to open the lister for commands and options"); + } + } + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: special-case view: pending + // + else if(str8_match(view_name, str8_lit("pending"), 0)) + { + Temp scratch = scratch_begin(0, 0); + typedef struct State State; + struct State + { + Arena *deferred_cmd_arena; + RD_CmdList deferred_cmds; + }; + State *state = rd_view_state(State); + if(state->deferred_cmd_arena == 0) + { + state->deferred_cmd_arena = rd_push_view_arena(); + } + rd_store_view_loading_info(1, 0, 0); + + // rjf: any commands sent to this view need to be deferred until loading is complete + for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) + { + RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); + switch(kind) + { + default:{}break; + case RD_CmdKind_GoToLine: + case RD_CmdKind_GoToAddress: + case RD_CmdKind_CenterCursor: + case RD_CmdKind_ContainCursor: + { + rd_cmd_list_push_new(state->deferred_cmd_arena, &state->deferred_cmds, cmd->name, cmd->regs); + }break; + } + } + + // rjf: unpack view's target expression & hash + String8 expr_string = rd_view_expr_string(); + E_Eval eval = e_eval_from_string(scratch.arena, expr_string); + Rng1U64 range = r1u64(0, 1024); + U128 key = rd_key_from_eval_space_range(eval.space, range, 0); + U128 hash = hs_hash_from_key(key, 0); + + // rjf: determine if hash's blob is ready, and which viewer to use + B32 data_is_ready = 0; + String8 new_view_name = {0}; + { + HS_Scope *hs_scope = hs_scope_open(); + if(!u128_match(hash, u128_zero())) + { + String8 data = hs_data_from_hash(hs_scope, hash); + U64 num_utf8_bytes = 0; + U64 num_unknown_bytes = 0; + for(U64 idx = 0; idx < data.size && idx < range.max;) + { + UnicodeDecode decode = utf8_decode(data.str+idx, data.size-idx); + if(decode.codepoint != max_U32 && (decode.inc > 1 || + (10 <= decode.codepoint && decode.codepoint <= 13) || + (32 <= decode.codepoint && decode.codepoint <= 126))) + { + num_utf8_bytes += decode.inc; + idx += decode.inc; + } + else + { + num_unknown_bytes += 1; + idx += 1; + } + } + data_is_ready = 1; + if(num_utf8_bytes > num_unknown_bytes*4 || num_unknown_bytes == 0) + { + new_view_name = str8_lit("text"); + } + else + { + new_view_name = str8_lit("memory"); + } + } + hs_scope_close(hs_scope); + } + + // rjf: if we don't have a viewer, just use the memory viewer. + if(new_view_name.size != 0) + { + new_view_name = str8_lit("memory"); + } + + // rjf: if data is ready and we have the name of a new visualizer, + // dispatch deferred commands & change this view's string to be + // that of the new visualizer. + if(data_is_ready && new_view_name.size != 0) + { + for(RD_CmdNode *cmd_node = state->deferred_cmds.first; + cmd_node != 0; + cmd_node = cmd_node->next) + { + RD_Cmd *cmd = &cmd_node->cmd; + rd_push_cmd(cmd->name, cmd->regs); + } + RD_Cfg *view = rd_cfg_from_id(rd_regs()->view); + rd_cfg_equip_string(view, new_view_name); + } + + // rjf: if we don't have a viewer, for whatever reason, then just + // close the tab. + if(data_is_ready && new_view_name.size == 0) + { + rd_cmd(RD_CmdKind_CloseTab); + } + + scratch_end(scratch); + } + + ////////////////////////////// + //- rjf: visualizer hook + // + else + { + Temp scratch = scratch_begin(0, 0); + RD_ViewUIRule *view_ui_rule = rd_view_ui_rule_from_string(view_name); + E_Eval expr_eval = e_eval_from_string(scratch.arena, expr_string); + E_Expr *tag = rd_tag_from_cfg(scratch.arena, view); + view_ui_rule->ui(expr_eval, tag, rect); + scratch_end(scratch); + } + + ProfEnd(); +} + //////////////////////////////// //~ rjf: View Building API @@ -2786,6 +3097,117 @@ rd_view_filter(void) return filter_string; } +internal RD_Cfg * +rd_view_cfg_from_string(String8 string) +{ + RD_Cfg *view = rd_cfg_from_id(rd_regs()->view); + RD_Cfg *cfg = rd_cfg_child_from_string(view, string); + return cfg; +} + +internal E_Value +rd_view_cfg_value_from_string(String8 string) +{ + Temp scratch = scratch_begin(0, 0); + RD_Cfg *root = rd_view_cfg_from_string(string); + String8 expr = root->first->string; + E_Eval eval = e_eval_from_string(scratch.arena, expr); + E_Value result = e_value_eval_from_eval(eval).value; + scratch_end(scratch); + return result; +} + +//- rjf: evaluation & tag (a view's 'call') parameter extraction + +internal U64 +rd_base_offset_from_eval(E_Eval eval) +{ + if(e_type_kind_is_pointer_or_ref(e_type_kind_from_key(eval.type_key))) + { + eval = e_value_eval_from_eval(eval); + } + return eval.value.u64; +} + +internal Rng1U64 +rd_range_from_eval_tag(E_Eval eval, E_Expr *tag) +{ + Temp scratch = scratch_begin(0, 0); + U64 size = 0; + for(E_Expr *param = tag->first->next; param != &e_expr_nil; param = param->next) + { + if(param->kind == E_ExprKind_Define && str8_match(param->first->string, str8_lit("size"), 0)) + { + size = e_eval_from_expr(scratch.arena, param->first->next).value.u64; + break; + } + } + E_TypeKey type_key = e_type_unwrap(eval.type_key); + E_TypeKind type_kind = e_type_kind_from_key(type_key); + E_TypeKey direct_type_key = e_type_unwrap(e_type_direct_from_key(eval.type_key)); + E_TypeKind direct_type_kind = e_type_kind_from_key(direct_type_key); + if(size == 0 && e_type_kind_is_pointer_or_ref(type_kind) && (direct_type_kind == E_TypeKind_Struct || + direct_type_kind == E_TypeKind_Union || + direct_type_kind == E_TypeKind_Class || + direct_type_kind == E_TypeKind_Array)) + { + size = e_type_byte_size_from_key(e_type_direct_from_key(e_type_unwrap(eval.type_key))); + } + if(size == 0 && eval.mode == E_Mode_Offset && (type_kind == E_TypeKind_Struct || + type_kind == E_TypeKind_Union || + type_kind == E_TypeKind_Class || + type_kind == E_TypeKind_Array)) + { + size = e_type_byte_size_from_key(e_type_unwrap(eval.type_key)); + } + if(size == 0) + { + size = KB(16); + } + Rng1U64 result = {0}; + result.min = rd_base_offset_from_eval(eval); + result.max = result.min + size; + scratch_end(scratch); + return result; +} + +internal TXT_LangKind +rd_lang_kind_from_eval_tag(E_Eval eval, E_Expr *tag) +{ + TXT_LangKind lang_kind = TXT_LangKind_Null; + if(eval.expr->kind == E_ExprKind_LeafFilePath) + { + lang_kind = txt_lang_kind_from_extension(str8_skip_last_dot(eval.expr->string)); + } + else for(E_Expr *param = tag->first->next; param != &e_expr_nil; param = param->next) + { + if(param->kind == E_ExprKind_Define && str8_match(param->first->string, str8_lit("lang"), 0)) + { + lang_kind = txt_lang_kind_from_extension(param->first->next->string); + break; + } + } + return lang_kind; +} + +internal Arch +rd_arch_from_eval_tag(E_Eval eval, E_Expr *tag) +{ + +} + +internal Vec2S32 +rd_dim2s32_from_eval_tag(E_Eval eval, E_Expr *tag) +{ + +} + +internal R_Tex2DFormat +rd_tex2dformat_from_eval_tag(E_Eval eval, E_Expr *tag) +{ + +} + //- rjf: pushing/attaching view resources internal void * @@ -3454,8 +3876,6 @@ rd_window_frame(void) { Temp scratch = scratch_begin(0, 0); RD_Cfg *view = rd_cfg_from_id(rd_state->drag_drop_regs->view); - RD_Cfg *query = rd_cfg_child_from_string(view, str8_lit("expression")); - RD_ViewRuleInfo *view_rule_info = rd_view_rule_info_from_string(view->string); { //- rjf: tab dragging if(rd_state->drag_drop_regs_slot == RD_RegSlot_View && view != &rd_nil_cfg) @@ -3475,20 +3895,11 @@ rd_window_frame(void) UI_Box *container = ui_build_box_from_key(0, ui_key_zero()); UI_Parent(container) { - UI_Row + UI_Row UI_PrefWidth(ui_text_dim(10, 1)) { - RD_IconKind icon_kind = view_rule_info->icon_kind; - DR_FancyStringList fstrs = rd_title_fstrs_from_view(scratch.arena, view_rule_info->display_name, query->first->string, ui_top_palette()->text, ui_top_palette()->text_weak, ui_top_font_size()); - RD_Font(RD_FontSlot_Icons) - UI_FontSize(rd_font_size_from_slot(RD_FontSlot_Icons)) - UI_PrefWidth(ui_em(2.5f, 1.f)) - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - ui_label(rd_icon_kind_text_table[icon_kind]); - UI_PrefWidth(ui_text_dim(10, 1)) - { - UI_Box *name_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); - ui_box_equip_display_fancy_strings(name_box, &fstrs); - } + DR_FancyStringList fstrs = rd_title_fstrs_from_cfg(scratch.arena, view, ui_top_palette()->text_weak, ui_top_font_size()); + UI_Box *name_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); + ui_box_equip_display_fancy_strings(name_box, &fstrs); } ui_set_next_pref_width(ui_pct(1, 0)); ui_set_next_pref_height(ui_pct(1, 0)); @@ -3496,11 +3907,7 @@ rd_window_frame(void) UI_Box *view_preview_container = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "###view_preview_container"); UI_Parent(view_preview_container) UI_Focus(UI_FocusKind_Off) UI_WidthFill { - RD_ViewRuleUIFunctionType *view_ui = view_rule_info->ui; - String8 expr = rd_view_expr_string(); - String8 params_string = rd_string_from_cfg_tree(scratch.arena, view); - MD_Node *params = md_tree_from_string(scratch.arena, params_string)->first; - view_ui(expr, params, view_preview_container->rect); + rd_view_ui(view_preview_container->rect); } } } @@ -4318,6 +4725,7 @@ rd_window_frame(void) // case RD_RegSlot_View: { +#if 0 // TODO(rjf): @cfg RD_Cfg *tab = rd_cfg_from_id(regs->view); RD_RegsScope(.view = regs->view) { @@ -4440,6 +4848,7 @@ rd_window_frame(void) } #endif } +#endif }break; ////////////////////// @@ -5720,7 +6129,6 @@ rd_window_frame(void) RD_Cfg *expr = rd_cfg_child_from_string_or_alloc(view, str8_lit("expression")); RD_RegsScope(.panel = 0, .view = view->id) { - RD_ViewRuleInfo *view_rule_info = rd_view_rule_info_from_string(view->string); rd_cfg_new_replace(expr, ws->hover_eval_string); EV_BlockTree predicted_block_tree = ev_block_tree_from_string(scratch.arena, rd_view_eval_view(), str8_zero(), ws->hover_eval_string); F32 row_height_px = floor_f32(ui_top_font_size()*2.5f); @@ -5769,10 +6177,7 @@ rd_window_frame(void) UI_Box *view_contents_container = ui_build_box_from_stringf(UI_BoxFlag_DrawBorder|UI_BoxFlag_DrawBackground|UI_BoxFlag_Clip, "###view_contents_container"); UI_Parent(view_contents_container) UI_WidthFill { - RD_ViewRuleUIFunctionType *view_ui = view_rule_info->ui; - String8 params_string = rd_string_from_cfg_tree(scratch.arena, view); - MD_Node *params = md_tree_from_string(scratch.arena, params_string)->first; - view_ui(expr->first->string, params, view_contents_container->rect); + rd_view_ui(view_contents_container->rect); } } UI_Signal sig = ui_signal_from_box(container); @@ -6777,6 +7182,7 @@ rd_window_frame(void) ////////////////////////// //- rjf: build filtering box // +#if 0 // TODO(rjf): @cfg { RD_Cfg *view = selected_tab; RD_ViewRuleInfo *view_rule_info = rd_view_rule_info_from_string(view->string); @@ -6831,6 +7237,7 @@ rd_window_frame(void) } } } +#endif ////////////////////////// //- rjf: panel not selected? -> darken @@ -6879,7 +7286,7 @@ rd_window_frame(void) rd_push_regs(.panel = panel->cfg->id, .view = selected_tab->id); { - String8 view_expr = rd_view_expr_string(); + String8 view_expr = rd_expr_from_cfg(selected_tab); String8 view_file_path = rd_file_path_from_eval_string(rd_frame_arena(), view_expr); if(view_file_path.size != 0) { @@ -6899,18 +7306,30 @@ rd_window_frame(void) //- rjf: build empty view UI_Parent(view_container_box) if(selected_tab == &rd_nil_cfg) { - RD_VIEW_RULE_UI_FUNCTION_NAME(empty)(str8_zero(), &md_nil_node, content_rect); + ui_set_next_flags(UI_BoxFlag_DefaultFocusNav); + UI_Focus(UI_FocusKind_On) UI_WidthFill UI_HeightFill UI_NamedColumn(str8_lit("empty_view")) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) + UI_Padding(ui_pct(1, 0)) UI_Focus(UI_FocusKind_Null) + { + UI_PrefHeight(ui_em(3.f, 1.f)) + UI_Row + UI_Padding(ui_pct(1, 0)) + UI_TextAlignment(UI_TextAlign_Center) + UI_PrefWidth(ui_em(15.f, 1.f)) + UI_CornerRadius(ui_top_font_size()/2.f) + RD_Palette(RD_PaletteCode_NegativePopButton) + { + if(ui_clicked(rd_icon_buttonf(RD_IconKind_X, 0, "Close Panel"))) + { + rd_cmd(RD_CmdKind_ClosePanel); + } + } + } } //- rjf: build tab view UI_Parent(view_container_box) if(selected_tab != &rd_nil_cfg) ProfScope("build tab view") { - String8 view_expr = rd_expr_from_cfg(selected_tab); - String8 params_string = rd_string_from_cfg_tree(scratch.arena, selected_tab); - MD_Node *params = md_tree_from_string(scratch.arena, params_string)->first; - RD_ViewRuleInfo *view_rule_info = rd_view_rule_info_from_string(selected_tab->string); - RD_ViewRuleUIFunctionType *view_ui = view_rule_info->ui; - view_ui(view_expr, params, content_rect); + rd_view_ui(content_rect); } //- rjf: pop interaction registers; commit if this is the selected view @@ -6935,6 +7354,7 @@ rd_window_frame(void) ////////////////////////// //- rjf: take events to automatically start/end filtering, if applicable // +#if 0 // TODO(rjf): @cfg UI_Focus(UI_FocusKind_On) { RD_Cfg *view = selected_tab; @@ -6963,6 +7383,7 @@ rd_window_frame(void) rd_cmd(RD_CmdKind_ClearFilter); } } +#endif ////////////////////////// //- rjf: consume panel fallthrough interaction events @@ -7037,7 +7458,6 @@ rd_window_frame(void) { prev_tab = tab; tab = tab_n->v; - RD_ViewRuleInfo *tab_view_rule_info = rd_view_rule_info_from_string(tab->string); temp_end(scratch); if(rd_cfg_is_project_filtered(tab)) { continue; } @@ -7078,9 +7498,7 @@ rd_window_frame(void) { // rjf: gather info for this tab B32 view_is_selected = (tab == panel->selected_tab); - RD_IconKind icon_kind = tab_view_rule_info->icon_kind; - String8 view_expr = rd_view_expr_string(); - DR_FancyStringList title_fstrs = rd_title_fstrs_from_view(scratch.arena, tab_view_rule_info->display_name, view_expr, ui_top_palette()->text, ui_top_palette()->text_weak, ui_top_font_size()); + DR_FancyStringList title_fstrs = rd_title_fstrs_from_cfg(scratch.arena, tab, ui_top_palette()->text_weak, ui_top_font_size()); // rjf: begin vertical region for this tab ui_set_next_child_layout_axis(Axis2_Y); @@ -7111,14 +7529,6 @@ rd_window_frame(void) UI_WidthFill UI_Row { ui_spacer(ui_em(0.5f, 1.f)); - if(icon_kind != RD_IconKind_Null) - { - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - RD_Font(RD_FontSlot_Icons) - UI_TextAlignment(UI_TextAlign_Center) - UI_PrefWidth(ui_em(1.75f, 1.f)) - ui_label(rd_icon_kind_text_table[icon_kind]); - } UI_PrefWidth(ui_text_dim(10, 0)) { UI_Box *name_box = ui_build_box_from_key(UI_BoxFlag_DrawText, ui_key_zero()); @@ -9733,6 +10143,7 @@ rd_lister_item_array_from_regs_needle_cursor_off(Arena *arena, RD_Regs *regs, St //- rjf: gather settings if(flags & RD_ListerFlag_Settings) { +#if 0 // TODO(rjf): @cfg String8List schema_strings = {0}; // rjf: push schema for view @@ -9765,6 +10176,7 @@ rd_lister_item_array_from_regs_needle_cursor_off(Arena *arena, RD_Regs *regs, St } } } +#endif } //- rjf: gather system processes @@ -11257,6 +11669,20 @@ rd_next_cmd(RD_Cmd **cmd) return !!cmd[0]; } +internal B32 +rd_next_view_cmd(RD_Cmd **cmd) +{ + for(;rd_next_cmd(cmd);) + { + if(rd_regs()->view == cmd[0]->regs->view) + { + break; + } + } + B32 result = !!cmd[0]; + return result; +} + //////////////////////////////// //~ rjf: Main Layer Top-Level Calls @@ -12549,6 +12975,18 @@ rd_frame(void) e_push_leaf_ident_exprs_from_expr__in_place(scratch.arena, ctx->macro_map, parse.expr); } } + + //- rjf: add auto-hook rules for auto-view-rules + { + RD_CfgList auto_view_rules = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("auto_view_rule")); + for(RD_CfgNode *n = auto_view_rules.first; n != 0; n = n->next) + { + RD_Cfg *rule = n->v; + String8 type_string = rd_cfg_child_from_string(rule, str8_lit("source"))->first->string; + String8 view_rule_string = rd_cfg_child_from_string(rule, str8_lit("dest"))->first->string; + e_auto_hook_map_insert_new(scratch.arena, ctx->auto_hook_map, .type_pattern = type_string, .tag_expr_string = view_rule_string); + } + } } e_select_ir_ctx(ir_ctx); @@ -12572,34 +13010,38 @@ rd_frame(void) e_select_interpret_ctx(interpret_ctx); //////////////////////////// - //- rjf: build eval visualization expand rule table + //- rjf: build eval expand rule table // EV_ExpandRuleTable *expand_rule_table = push_array(scratch.arena, EV_ExpandRuleTable, 1); ev_select_expand_rule_table(expand_rule_table); //////////////////////////// - //- rjf: build eval visualization auto-view-rule table + //- rjf: build view ui rule map // - // TODO(rjf): @cfg - // - EV_AutoViewRuleTable *auto_view_rule_table = push_array(scratch.arena, EV_AutoViewRuleTable, 1); + rd_state->view_ui_rule_map = rd_view_ui_rule_map_make(scratch.arena, 512); { - RD_CfgList auto_view_rules = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("auto_view_rule")); - for(RD_CfgNode *n = auto_view_rules.first; n != 0; n = n->next) + // TODO(rjf): generate via metaprogram + struct { - RD_Cfg *rule = n->v; - String8 type_string = rd_cfg_child_from_string(rule, str8_lit("source"))->first->string; - String8 view_rule_string = rd_cfg_child_from_string(rule, str8_lit("dest"))->first->string; - E_TokenArray tokens = e_token_array_from_text(scratch.arena, type_string); - E_Parse type_parse = e_parse_type_from_text_tokens(scratch.arena, type_string, &tokens); - E_TypeKey type_key = e_type_from_expr(type_parse.expr); - if(!e_type_key_match(e_type_key_zero(), type_key)) - { - // ev_auto_view_rule_table_push_new(scratch.arena, auto_view_rule_table, type_key, view_rule_string, 0); - } + String8 name; + RD_ViewUIFunctionType *ui; + } + table[] = + { + {str8_lit("watch"), RD_VIEW_UI_FUNCTION_NAME(watch)}, + {str8_lit("text"), RD_VIEW_UI_FUNCTION_NAME(text)}, + {str8_lit("disasm"), RD_VIEW_UI_FUNCTION_NAME(disasm)}, + {str8_lit("memory"), RD_VIEW_UI_FUNCTION_NAME(memory)}, + {str8_lit("bitmap"), RD_VIEW_UI_FUNCTION_NAME(bitmap)}, + {str8_lit("checkbox"), RD_VIEW_UI_FUNCTION_NAME(checkbox)}, + {str8_lit("color_rgba"), RD_VIEW_UI_FUNCTION_NAME(color_rgba)}, + {str8_lit("geo3d"), RD_VIEW_UI_FUNCTION_NAME(geo3d)}, + }; + for EachElement(idx, table) + { + rd_view_ui_rule_map_insert(scratch.arena, rd_state->view_ui_rule_map, table[idx].name, table[idx].ui); } } - // ev_select_auto_view_rule_table(auto_view_rule_table); //////////////////////////// //- rjf: autosave if needed @@ -12691,11 +13133,13 @@ rd_frame(void) } // rjf: try to open tabs for "view driver" commands +#if 0 // TODO(rjf): @cfg RD_ViewRuleInfo *view_rule_info = rd_view_rule_info_from_string(cmd->name); if(view_rule_info != &rd_nil_view_rule_info) { rd_cmd(RD_CmdKind_OpenTab, .string = str8_zero(), .params_tree = md_tree_from_string(scratch.arena, cmd->name)->first); } +#endif }break; //- rjf: top-level lister @@ -13684,9 +14128,11 @@ rd_frame(void) if(props.created != 0) { rd_cmd(RD_CmdKind_RecordFileInProject); +#if 0 // TODO(rjf): @cfg rd_cmd(RD_CmdKind_OpenTab, .string = rd_eval_string_from_file_path(scratch.arena, path), .params_tree = md_tree_from_string(scratch.arena, rd_view_rule_kind_info_table[RD_ViewRuleKind_PendingFile].string)->first); +#endif } else { @@ -14377,8 +14823,7 @@ Z(getting_started) { String8 tab_expr = rd_view_expr_string(); String8 tab_file_path = rd_file_path_from_eval_string(scratch.arena, tab_expr); - RD_ViewRuleKind tab_view_kind = rd_view_rule_kind_from_string(tab->string); - if((tab_view_kind == RD_ViewRuleKind_Text || tab_view_kind == RD_ViewRuleKind_PendingFile) && + if((str8_match(tab->string, str8_lit("text"), 0) || str8_match(tab->string, str8_lit("pending"), 0)) && path_match_normalized(tab_file_path, file_path)) { panel_w_this_src_code = panel; @@ -14412,10 +14857,9 @@ Z(getting_started) { RD_Cfg *tab = tab_n->v; if(rd_cfg_is_project_filtered(tab)) { continue; } - RD_ViewRuleKind view_kind = rd_view_rule_kind_from_string(tab->string); String8 view_expr = rd_expr_from_cfg(tab); String8 file_path = rd_file_path_from_eval_string(scratch.arena, view_expr); - if(view_kind == RD_ViewRuleKind_Text && file_path.size != 0 && panel_area > best_panel_area) + if(str8_match(tab->string, str8_lit("text"), 0) && file_path.size != 0 && panel_area > best_panel_area) { panel_w_any_src_code = panel; best_panel_area = panel_area; @@ -14449,9 +14893,8 @@ Z(getting_started) RD_RegsScope(.view = tab->id) { B32 tab_is_selected = (tab == panel->selected_tab); - RD_ViewRuleKind view_kind = rd_view_rule_kind_from_string(tab->string); String8 expr_string = rd_view_expr_string(); - if(view_kind == RD_ViewRuleKind_Disasm && expr_string.size == 0 && panel_area > best_panel_area) + if(str8_match(tab->string, str8_lit("disasm"), 0) && expr_string.size == 0 && panel_area > best_panel_area) { panel_w_disasm = panel; view_w_disasm = tab; diff --git a/src/raddbg/raddbg_core.h b/src/raddbg/raddbg_core.h index 289b7de6..ab55cf8e 100644 --- a/src/raddbg/raddbg_core.h +++ b/src/raddbg/raddbg_core.h @@ -25,7 +25,7 @@ struct RD_CfgIDList }; //////////////////////////////// -//~ rjf: Key Binding Types +//~ rjf: Key Bindings typedef struct RD_Binding RD_Binding; struct RD_Binding @@ -94,6 +94,42 @@ enum RD_EvalSpaceKind_MetaCmd, }; +//////////////////////////////// +//~ rjf: View UI Hook Types + +#define RD_VIEW_UI_FUNCTION_SIG(name) void name(E_Eval eval, E_Expr *tag, Rng2F32 rect) +#define RD_VIEW_UI_FUNCTION_NAME(name) rd_view_ui__##name +#define RD_VIEW_UI_FUNCTION_DEF(name) internal RD_VIEW_UI_FUNCTION_SIG(RD_VIEW_UI_FUNCTION_NAME(name)) +typedef RD_VIEW_UI_FUNCTION_SIG(RD_ViewUIFunctionType); + +typedef struct RD_ViewUIRule RD_ViewUIRule; +struct RD_ViewUIRule +{ + String8 name; + RD_ViewUIFunctionType *ui; +}; + +typedef struct RD_ViewUIRuleNode RD_ViewUIRuleNode; +struct RD_ViewUIRuleNode +{ + RD_ViewUIRuleNode *next; + RD_ViewUIRule v; +}; + +typedef struct RD_ViewUIRuleSlot RD_ViewUIRuleSlot; +struct RD_ViewUIRuleSlot +{ + RD_ViewUIRuleNode *first; + RD_ViewUIRuleNode *last; +}; + +typedef struct RD_ViewUIRuleMap RD_ViewUIRuleMap; +struct RD_ViewUIRuleMap +{ + RD_ViewUIRuleSlot *slots; + U64 slots_count; +}; + //////////////////////////////// //~ rjf: View Rule Info Types @@ -721,6 +757,9 @@ struct RD_State RD_Cfg2EvalBlobMap *cfg2evalblob_map; RD_Entity2EvalBlobMap *entity2evalblob_map; + // rjf: name -> view ui map (constructed from-scratch each frame) + RD_ViewUIRuleMap *view_ui_rule_map; + // rjf: registers stack RD_RegsNode base_regs; RD_RegsNode *top_regs; @@ -841,6 +880,14 @@ read_only global RD_PanelNode rd_nil_panel_node = read_only global RD_CmdKindInfo rd_nil_cmd_kind_info = {0}; +RD_VIEW_UI_FUNCTION_DEF(null); +read_only global RD_ViewUIRule rd_nil_view_ui_rule = +{ + {0}, + RD_VIEW_UI_FUNCTION_NAME(null), +}; + +#if 0 // TODO(rjf): @cfg read_only global RD_ViewRuleInfo rd_nil_view_rule_info = { {0}, @@ -852,6 +899,7 @@ read_only global RD_ViewRuleInfo rd_nil_view_rule_info = EV_EXPAND_RULE_INFO_FUNCTION_NAME(nil), RD_VIEW_RULE_UI_FUNCTION_NAME(null) }; +#endif read_only global RD_ViewState rd_nil_view_state = { @@ -891,9 +939,19 @@ internal void rd_cmd_list_push_new(Arena *arena, RD_CmdList *cmds, String8 name, //////////////////////////////// //~ rjf: View Spec Type Functions +#if 0 // TODO(rjf): @cfg internal RD_ViewRuleKind rd_view_rule_kind_from_string(String8 string); internal RD_ViewRuleInfo *rd_view_rule_info_from_kind(RD_ViewRuleKind kind); internal RD_ViewRuleInfo *rd_view_rule_info_from_string(String8 string); +#endif + +//////////////////////////////// +//~ rjf: View UI Rule Functions + +internal RD_ViewUIRuleMap *rd_view_ui_rule_map_make(Arena *arena, U64 slots_count); +internal void rd_view_ui_rule_map_insert(Arena *arena, RD_ViewUIRuleMap *map, String8 string, RD_ViewUIFunctionType *ui); + +internal RD_ViewUIRule *rd_view_ui_rule_from_string(String8 string); //////////////////////////////// //~ rjf: Global Cross-Window UI Interaction State Functions @@ -977,6 +1035,8 @@ internal RD_Cfg *rd_immediate_cfg_from_keyf(char *fmt, ...); internal String8 rd_mapped_from_file_path(Arena *arena, String8 file_path); internal String8List rd_possible_overrides_from_file_path(Arena *arena, String8 file_path); +internal E_Expr *rd_tag_from_cfg(Arena *arena, RD_Cfg *cfg); + //////////////////////////////// //~ rjf: Control Entity Info Extraction @@ -1023,7 +1083,6 @@ internal Rng1U64 rd_whole_range_from_eval_space(E_Space space); internal B32 rd_commit_eval_value_string(E_Eval dst_eval, String8 string, B32 string_needs_unescaping); //- rjf: eval / view rule params tree info extraction -internal U64 rd_base_offset_from_eval(E_Eval eval); internal E_Value rd_value_from_params_key(MD_Node *params, String8 key); internal Rng1U64 rd_range_from_eval_params(E_Eval eval, MD_Node *params); internal TXT_LangKind rd_lang_kind_from_eval_params(E_Eval eval, MD_Node *params); @@ -1040,6 +1099,7 @@ internal String8 rd_eval_string_from_file_path(Arena *arena, String8 string); internal RD_ViewState *rd_view_state_from_cfg(RD_Cfg *cfg); internal DR_FancyStringList rd_title_fstrs_from_view(Arena *arena, String8 viewer_name_string, String8 query, Vec4F32 primary_color, Vec4F32 secondary_color, F32 size); +internal void rd_view_ui(Rng2F32 rect); //////////////////////////////// //~ rjf: View Building API @@ -1050,6 +1110,16 @@ internal UI_ScrollPt2 rd_view_scroll_pos(void); internal EV_View *rd_view_eval_view(void); internal String8 rd_view_expr_string(void); internal String8 rd_view_filter(void); +internal RD_Cfg *rd_view_cfg_from_string(String8 string); +internal E_Value rd_view_cfg_value_from_string(String8 string); + +//- rjf: evaluation & tag (a view's 'call') parameter extraction +internal U64 rd_base_offset_from_eval(E_Eval eval); +internal Rng1U64 rd_range_from_eval_tag(E_Eval eval, E_Expr *tag); +internal TXT_LangKind rd_lang_kind_from_eval_tag(E_Eval eval, E_Expr *tag); +internal Arch rd_arch_from_eval_tag(E_Eval eval, E_Expr *tag); +internal Vec2S32 rd_dim2s32_from_eval_tag(E_Eval eval, E_Expr *tag); +internal R_Tex2DFormat rd_tex2dformat_from_eval_tag(E_Eval eval, E_Expr *tag); //- rjf: pushing/attaching view resources internal void *rd_view_state_by_size(U64 size); @@ -1185,6 +1255,7 @@ internal void rd_push_cmd(String8 name, RD_Regs *regs); //- rjf: iterating internal B32 rd_next_cmd(RD_Cmd **cmd); +internal B32 rd_next_view_cmd(RD_Cmd **cmd); //////////////////////////////// //~ rjf: Main Layer Top-Level Calls diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index ba7cd8ce..c25e69e3 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -55,15 +55,8 @@ rd_code_view_build(Arena *arena, RD_CodeViewState *cv, RD_CodeViewBuildFlags fla ////////////////////////////// //- rjf: process commands // - for(RD_Cmd *cmd = 0; rd_next_cmd(&cmd);) + for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { - // rjf: mismatched window/panel => skip - if(rd_regs()->view != cmd->regs->view) - { - continue; - } - - // rjf: process RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { @@ -3995,166 +3988,12 @@ rd_watch_view_build(RD_WatchViewState *ewv, Rng2F32 rect) //////////////////////////////// //~ rjf: null @view_hook_impl -RD_VIEW_RULE_UI_FUNCTION_DEF(null) {} - -//////////////////////////////// -//~ rjf: empty @view_hook_impl - -RD_VIEW_RULE_UI_FUNCTION_DEF(empty) -{ - ui_set_next_flags(UI_BoxFlag_DefaultFocusNav); - UI_Focus(UI_FocusKind_On) UI_WidthFill UI_HeightFill UI_NamedColumn(str8_lit("empty_view")) UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - UI_Padding(ui_pct(1, 0)) UI_Focus(UI_FocusKind_Null) - { - UI_PrefHeight(ui_em(3.f, 1.f)) - UI_Row - UI_Padding(ui_pct(1, 0)) - UI_TextAlignment(UI_TextAlign_Center) - UI_PrefWidth(ui_em(15.f, 1.f)) - UI_CornerRadius(ui_top_font_size()/2.f) - RD_Palette(RD_PaletteCode_NegativePopButton) - { - if(ui_clicked(rd_icon_buttonf(RD_IconKind_X, 0, "Close Panel"))) - { - rd_cmd(RD_CmdKind_ClosePanel); - } - } - } -} - -//////////////////////////////// -//~ rjf: getting_started @view_hook_impl - -RD_VIEW_RULE_UI_FUNCTION_DEF(getting_started) -{ - ProfBeginFunction(); - Temp scratch = scratch_begin(0, 0); - ui_set_next_flags(UI_BoxFlag_DefaultFocusNav); - UI_Focus(UI_FocusKind_On) UI_WidthFill UI_HeightFill UI_NamedColumn(str8_lit("empty_view")) - UI_FlagsAdd(UI_BoxFlag_DrawTextWeak) - UI_Padding(ui_pct(1, 0)) UI_Focus(UI_FocusKind_Null) - { - RD_CfgList targets = rd_cfg_top_level_list_from_string(scratch.arena, str8_lit("target")); - CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process); - - //- rjf: icon & info - UI_Padding(ui_em(2.f, 1.f)) - { - //- rjf: icon - { - F32 icon_dim = ui_top_font_size()*10.f; - UI_PrefHeight(ui_px(icon_dim, 1.f)) - UI_Row - UI_Padding(ui_pct(1, 0)) - UI_PrefWidth(ui_px(icon_dim, 1.f)) - { - R_Handle texture = rd_state->icon_texture; - Vec2S32 texture_dim = r_size_from_tex2d(texture); - ui_image(texture, R_Tex2DSampleKind_Linear, r2f32p(0, 0, texture_dim.x, texture_dim.y), v4f32(1, 1, 1, 1), 0, str8_lit("")); - } - } - - //- rjf: info - UI_Padding(ui_em(2.f, 1.f)) - UI_WidthFill UI_PrefHeight(ui_em(2.f, 1.f)) - UI_Row - UI_Padding(ui_pct(1, 0)) - UI_TextAlignment(UI_TextAlign_Center) - UI_PrefWidth(ui_text_dim(10, 1)) - { - ui_label(str8_lit(BUILD_TITLE_STRING_LITERAL)); - } - } - - //- rjf: targets state dependent helper - B32 helper_built = 0; - if(processes.count == 0) - { - helper_built = 1; - switch(targets.count) - { - //- rjf: user has no targets. build helper for adding them - case 0: - { - UI_PrefHeight(ui_em(3.75f, 1.f)) - UI_Row - UI_Padding(ui_pct(1, 0)) - UI_TextAlignment(UI_TextAlign_Center) - UI_PrefWidth(ui_em(22.f, 1.f)) - UI_CornerRadius(ui_top_font_size()/2.f) - RD_Palette(RD_PaletteCode_NeutralPopButton) - if(ui_clicked(rd_icon_buttonf(RD_IconKind_Add, 0, "Add Target"))) - { - rd_cmd(RD_CmdKind_RunCommand, .cmd_name = rd_cmd_kind_info_table[RD_CmdKind_AddTarget].string); - } - }break; - - //- rjf: user has 1 target. build helper for launching it - case 1: - { - RD_Cfg *target_cfg = rd_cfg_list_first(&targets); - D_Target target = rd_target_from_cfg(scratch.arena, target_cfg); - String8 target_full_path = target.exe; - String8 target_name = str8_skip_last_slash(target_full_path); - UI_PrefHeight(ui_em(3.75f, 1.f)) - UI_Row - UI_Padding(ui_pct(1, 0)) - UI_TextAlignment(UI_TextAlign_Center) - UI_PrefWidth(ui_em(22.f, 1.f)) - UI_CornerRadius(ui_top_font_size()/2.f) - RD_Palette(RD_PaletteCode_PositivePopButton) - { - if(ui_clicked(rd_icon_buttonf(RD_IconKind_Play, 0, "Launch %S", target_name))) - { - rd_cmd(RD_CmdKind_LaunchAndRun, .cfg = target_cfg->id); - } - ui_spacer(ui_em(1.5f, 1)); - if(ui_clicked(rd_icon_buttonf(RD_IconKind_Play, 0, "Step Into %S", target_name))) - { - rd_cmd(RD_CmdKind_LaunchAndInit, .cfg = target_cfg->id); - } - } - }break; - - //- rjf: user has N targets. - default: - { - helper_built = 0; - }break; - } - } - - //- rjf: or text - if(helper_built) - { - UI_PrefHeight(ui_em(2.25f, 1.f)) - UI_Row - UI_Padding(ui_pct(1, 0)) - UI_TextAlignment(UI_TextAlign_Center) - UI_WidthFill - ui_labelf("- or -"); - } - - //- rjf: helper text for command lister activation - UI_PrefHeight(ui_em(2.25f, 1.f)) UI_Row - UI_PrefWidth(ui_text_dim(10, 1)) - UI_TextAlignment(UI_TextAlign_Center) - UI_Padding(ui_pct(1, 0)) - RD_Palette(RD_PaletteCode_Floating) - { - ui_labelf("use"); - UI_TextAlignment(UI_TextAlign_Center) rd_cmd_binding_buttons(rd_cmd_kind_info_table[RD_CmdKind_OpenLister].string); - ui_labelf("to open the lister for commands and options"); - } - } - scratch_end(scratch); - ProfEnd(); -} +RD_VIEW_UI_FUNCTION_DEF(null) {} //////////////////////////////// //~ rjf: watch @view_hook_impl -RD_VIEW_RULE_UI_FUNCTION_DEF(watch) +RD_VIEW_UI_FUNCTION_DEF(watch) { ProfBeginFunction(); RD_WatchViewState *wv = rd_view_state(RD_WatchViewState); @@ -4170,136 +4009,6 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(watch) ProfEnd(); } -//////////////////////////////// -//~ rjf: pending_file @view_hook_impl - -typedef struct RD_PendingFileViewState RD_PendingFileViewState; -struct RD_PendingFileViewState -{ - Arena *deferred_cmd_arena; - RD_CmdList deferred_cmds; -}; - -RD_VIEW_RULE_UI_FUNCTION_DEF(pending_file) -{ - Temp scratch = scratch_begin(0, 0); - RD_PendingFileViewState *pves = rd_view_state(RD_PendingFileViewState); - if(pves->deferred_cmd_arena == 0) - { - pves->deferred_cmd_arena = rd_push_view_arena(); - } - rd_store_view_loading_info(1, 0, 0); - - ////////////////////////////// - //- rjf: process commands - // - for(RD_Cmd *cmd = 0; rd_next_cmd(&cmd);) - { - // rjf: mismatched window/panel => skip - if(rd_regs()->view != cmd->regs->view) - { - continue; - } - - // rjf: process - RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); - switch(kind) - { - default:break; - - // rjf: gather deferred commands to redispatch when entity is ready - case RD_CmdKind_GoToLine: - case RD_CmdKind_GoToAddress: - case RD_CmdKind_CenterCursor: - case RD_CmdKind_ContainCursor: - { - rd_cmd_list_push_new(pves->deferred_cmd_arena, &pves->deferred_cmds, cmd->name, cmd->regs); - }break; - } - } - - //- rjf: determine if file is ready, and which viewer to use - String8 expr_string = rd_view_expr_string(); - String8 file_path = rd_file_path_from_eval_string(scratch.arena, expr_string); - Rng1U64 file_range = r1u64(0, 1024); - U128 file_hash = fs_hash_from_path_range(file_path, file_range, 0); - B32 file_is_ready = 0; - RD_ViewRuleKind viewer_kind = RD_ViewRuleKind_Text; - { - HS_Scope *hs_scope = hs_scope_open(); - String8 data = hs_data_from_hash(hs_scope, file_hash); - if(!u128_match(file_hash, u128_zero())) - { - U64 num_utf8_bytes = 0; - U64 num_unknown_bytes = 0; - for(U64 idx = 0; idx < data.size && idx < file_range.max;) - { - UnicodeDecode decode = utf8_decode(data.str+idx, data.size-idx); - if(decode.codepoint != max_U32 && (decode.inc > 1 || - (10 <= decode.codepoint && decode.codepoint <= 13) || - (32 <= decode.codepoint && decode.codepoint <= 126))) - { - num_utf8_bytes += decode.inc; - idx += decode.inc; - } - else - { - num_unknown_bytes += 1; - idx += 1; - } - } - file_is_ready = 1; - if(num_utf8_bytes > num_unknown_bytes*4 || num_unknown_bytes == 0) - { - viewer_kind = RD_ViewRuleKind_Text; - } - else - { - viewer_kind = RD_ViewRuleKind_Memory; - } - } - hs_scope_close(hs_scope); - } - - //- rjf: if file is ready, dispatch all deferred commands - if(file_is_ready) - { - for(RD_CmdNode *cmd_node = pves->deferred_cmds.first; cmd_node != 0; cmd_node = cmd_node->next) - { - RD_Cmd *cmd = &cmd_node->cmd; - rd_push_cmd(cmd->name, cmd->regs); - } - arena_clear(pves->deferred_cmd_arena); - MemoryZeroStruct(&pves->deferred_cmds); - } - - //- rjf: if file is ready, move params tree to scratch for new command -#if 0 // TODO(rjf): @cfg - MD_Node *params_copy = &md_nil_node; - if(file_is_ready) - { - params_copy = md_tree_copy(scratch.arena, params); - } - - //- rjf: if file is ready, replace this view with the correct one, if any viewer is specified - if(file_is_ready && viewer_kind != RD_ViewRuleKind_Null) - { - RD_ViewRuleInfo *view_rule_info = rd_view_rule_info_from_kind(viewer_kind); - String8 query = rd_eval_string_from_file_path(scratch.arena, file_path); - RD_View *view = rd_view_from_handle(rd_regs()->view); - rd_view_equip_spec(view, view_rule_info, query, params_copy); - } -#endif - - //- rjf: if entity is ready, but we have no viewer for it, then just close this tab - if(file_is_ready && viewer_kind == RD_ViewRuleKind_Null) - { - rd_cmd(RD_CmdKind_CloseTab); - } - - scratch_end(scratch); -} - //////////////////////////////// //~ rjf: text @view_hook_impl @@ -4311,7 +4020,7 @@ EV_EXPAND_RULE_INFO_FUNCTION_DEF(text) return info; } -RD_VIEW_RULE_UI_FUNCTION_DEF(text) +RD_VIEW_UI_FUNCTION_DEF(text) { RD_CodeViewState *cv = rd_view_state(RD_CodeViewState); rd_code_view_init(cv); @@ -4329,15 +4038,8 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(text) ////////////////////////////// //- rjf: process code-file commands // - ProfScope("process code-file commands") for(RD_Cmd *cmd = 0; rd_next_cmd(&cmd);) + ProfScope("process code-file commands") for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { - // rjf: mismatched window/panel => skip - if(rd_regs()->view != cmd->regs->view) - { - continue; - } - - // rjf: process RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { @@ -4364,30 +4066,23 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(text) //- rjf: unpack parameterization info // ProfBegin("unpack parameterization info"); - String8 path = rd_file_path_from_eval_string(rd_frame_arena(), string); - rd_regs()->file_path = path; rd_regs()->vaddr = 0; rd_regs()->prefer_disasm = 0; - rd_regs()->cursor.line = rd_value_from_params_key(params, str8_lit("cursor_line")).s64; - rd_regs()->cursor.column = rd_value_from_params_key(params, str8_lit("cursor_column")).s64; - rd_regs()->mark.line = rd_value_from_params_key(params, str8_lit("mark_line")).s64; - rd_regs()->mark.column = rd_value_from_params_key(params, str8_lit("mark_column")).s64; + rd_regs()->cursor.line = rd_view_cfg_value_from_string(str8_lit("cursor_line")).s64; + rd_regs()->cursor.column = rd_view_cfg_value_from_string(str8_lit("cursor_column")).s64; + rd_regs()->mark.line = rd_view_cfg_value_from_string(str8_lit("mark_line")).s64; + rd_regs()->mark.column = rd_view_cfg_value_from_string(str8_lit("mark_column")).s64; if(rd_regs()->cursor.line == 0) { rd_regs()->cursor.line = 1; } if(rd_regs()->cursor.column == 0) { rd_regs()->cursor.column = 1; } - if(rd_regs()->mark.line == 0) { rd_regs()->mark.line = 1; } - if(rd_regs()->mark.column == 0) { rd_regs()->mark.column = 1; } - E_Eval eval = e_eval_from_string(scratch.arena, string); - Rng1U64 range = rd_range_from_eval_params(eval, params); + if(rd_regs()->mark.line == 0) { rd_regs()->mark.line = 1; } + if(rd_regs()->mark.column == 0) { rd_regs()->mark.column = 1; } + Rng1U64 range = rd_range_from_eval_tag(eval, tag); rd_regs()->text_key = rd_key_from_eval_space_range(eval.space, range, 1); - rd_regs()->lang_kind = rd_lang_kind_from_eval_params(eval, params); - if(rd_regs()->lang_kind == TXT_LangKind_Null && path.size != 0) - { - rd_regs()->lang_kind = txt_lang_kind_from_extension(str8_skip_last_dot(path)); - } + rd_regs()->lang_kind = rd_lang_kind_from_eval_tag(eval, tag); U128 hash = {0}; TXT_TextInfo info = txt_text_info_from_key_lang(txt_scope, rd_regs()->text_key, rd_regs()->lang_kind, &hash); String8 data = hs_data_from_hash(hs_scope, hash); - B32 file_is_missing = (path.size != 0 && os_properties_from_file_path(path).modified == 0); + B32 file_is_missing = (rd_regs()->file_path.size != 0 && os_properties_from_file_path(rd_regs()->file_path).modified == 0); B32 key_has_data = !u128_match(hash, u128_zero()) && info.lines_count; ProfEnd(); @@ -4405,7 +4100,7 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(text) UI_Palette(ui_build_palette(ui_top_palette(), .text = rd_rgba_from_theme_color(RD_ThemeColor_TextNegative))) { RD_Font(RD_FontSlot_Icons) ui_label(rd_icon_kind_text_table[RD_IconKind_WarningBig]); - ui_labelf("Could not find \"%S\".", path); + ui_labelf("Could not find \"%S\".", rd_regs()->file_path); } UI_PrefHeight(ui_em(3, 1)) UI_Row UI_Padding(ui_pct(1, 0)) @@ -4444,11 +4139,11 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(text) ////////////////////////////// //- rjf: unpack cursor info // - if(path.size != 0) + if(rd_regs()->file_path.size != 0) { CTRL_Entity *module = ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->module); DI_Key dbgi_key = ctrl_dbgi_key_from_module(module); - rd_regs()->lines = d_lines_from_dbgi_key_file_path_line_num(rd_frame_arena(), dbgi_key, path, rd_regs()->cursor.line); + rd_regs()->lines = d_lines_from_dbgi_key_file_path_line_num(rd_frame_arena(), dbgi_key, rd_regs()->file_path, rd_regs()->cursor.line); } ////////////////////////////// @@ -4457,7 +4152,7 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(text) B32 file_is_out_of_date = 0; String8 out_of_date_dbgi_name = {0}; { - U64 file_timestamp = fs_timestamp_from_path(path); + U64 file_timestamp = fs_timestamp_from_path(rd_regs()->file_path); if(file_timestamp != 0) { for(DI_KeyNode *n = dbgi_keys.first; n != 0; n = n->next) @@ -4512,9 +4207,9 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(text) } RD_Font(RD_FontSlot_Code) { - if(path.size != 0) + if(rd_regs()->file_path.size != 0) { - ui_label(path); + ui_label(rd_regs()->file_path); ui_spacer(ui_em(1.5f, 1)); } ui_labelf("Line: %I64d, Column: %I64d", rd_regs()->cursor.line, rd_regs()->cursor.column); @@ -4566,7 +4261,7 @@ EV_EXPAND_RULE_INFO_FUNCTION_DEF(disasm) return info; } -RD_VIEW_RULE_UI_FUNCTION_DEF(disasm) +RD_VIEW_UI_FUNCTION_DEF(disasm) { RD_DisasmViewState *dv = rd_view_state(RD_DisasmViewState); if(dv->initialized == 0) @@ -4591,19 +4286,19 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(disasm) // B32 auto_selected = 0; E_Space auto_space = {0}; - if(string.size == 0) + if(eval.space.kind == E_SpaceKind_Null) { if(dv->temp_look_vaddr != 0 && dv->temp_look_run_gen == ctrl_run_gen()) { auto_selected = 1; auto_space = rd_eval_space_from_ctrl_entity(ctrl_entity_from_handle(d_state->ctrl_entity_store, dv->temp_look_process), RD_EvalSpaceKind_CtrlEntity); - string = push_str8f(scratch.arena, "(0x%I64x & (~(0x4000 - 1)))", dv->temp_look_vaddr); + eval = e_eval_from_stringf(scratch.arena, "(0x%I64x & (~(0x4000 - 1)))", dv->temp_look_vaddr); } else { auto_selected = 1; auto_space = rd_eval_space_from_ctrl_entity(ctrl_entity_from_handle(d_state->ctrl_entity_store, rd_regs()->process), RD_EvalSpaceKind_CtrlEntity); - string = str8_lit("(rip.u64 & (~(0x4000 - 1)))"); + eval = e_eval_from_stringf(scratch.arena, "(rip.u64 & (~(0x4000 - 1)))"); } } @@ -4620,15 +4315,8 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(disasm) ////////////////////////////// //- rjf: process disassembly-specific commands // - for(RD_Cmd *cmd = 0; rd_next_cmd(&cmd);) + for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { - // rjf: mismatched window/panel => skip - if(rd_regs()->view != cmd->regs->view) - { - continue; - } - - // rjf: process RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { @@ -4648,7 +4336,6 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(disasm) ////////////////////////////// //- rjf: unpack parameterization info // - E_Eval eval = e_eval_from_string(scratch.arena, string); E_Space space = eval.space; if(auto_selected) { @@ -4791,7 +4478,7 @@ EV_EXPAND_RULE_INFO_FUNCTION_DEF(memory) return info; } -RD_VIEW_RULE_UI_FUNCTION_DEF(memory) +RD_VIEW_UI_FUNCTION_DEF(memory) { ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); @@ -4801,7 +4488,6 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(memory) ////////////////////////////// //- rjf: unpack parameterization info // - E_Eval eval = e_eval_from_string(scratch.arena, string); Rng1U64 space_range = {0}; // TODO(rjf): @cfg rd_range_from_eval_params(eval, params); if(eval.space.kind == 0) { @@ -4827,15 +4513,8 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(memory) ////////////////////////////// //- rjf: process commands // - for(RD_Cmd *cmd = 0; rd_next_cmd(&cmd);) + for(RD_Cmd *cmd = 0; rd_next_view_cmd(&cmd);) { - // rjf: mismatched window/panel => skip - if(rd_regs()->view != cmd->regs->view) - { - continue; - } - - // rjf: process RD_CmdKind kind = rd_cmd_kind_from_string(cmd->name); switch(kind) { @@ -5718,7 +5397,7 @@ EV_EXPAND_RULE_INFO_FUNCTION_DEF(bitmap) return info; } -RD_VIEW_RULE_UI_FUNCTION_DEF(bitmap) +RD_VIEW_UI_FUNCTION_DEF(bitmap) { Temp scratch = scratch_begin(0, 0); HS_Scope *hs_scope = hs_scope_open(); @@ -5727,7 +5406,6 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(bitmap) ////////////////////////////// //- rjf: evaluate expression // - E_Eval eval = e_eval_from_string(scratch.arena, string); Vec2S32 dim = {0}; // TODO(rjf): @cfg rd_dim2s32_from_eval_params(eval, params); R_Tex2DFormat fmt = R_Tex2DFormat_RGBA8; // TODO(rjf): @cfg rd_tex2dformat_from_eval_params(eval, params); U64 base_offset = rd_base_offset_from_eval(eval); @@ -5921,16 +5599,13 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(bitmap) //////////////////////////////// //~ rjf: "checkbox" -RD_VIEW_RULE_UI_FUNCTION_DEF(checkbox) +RD_VIEW_UI_FUNCTION_DEF(checkbox) { - Temp scratch = scratch_begin(0, 0); - E_Eval eval = e_eval_from_string(scratch.arena, string); E_Eval value_eval = e_value_eval_from_eval(eval); if(ui_clicked(rd_icon_buttonf(value_eval.value.u64 == 0 ? RD_IconKind_CheckHollow : RD_IconKind_CheckFilled, 0, "###check"))) { rd_commit_eval_value_string(eval, value_eval.value.u64 == 0 ? str8_lit("1") : str8_lit("0"), 0); } - scratch_end(scratch); } //////////////////////////////// @@ -5966,12 +5641,11 @@ EV_EXPAND_RULE_INFO_FUNCTION_DEF(color_rgba) return info; } -RD_VIEW_RULE_UI_FUNCTION_DEF(color_rgba) +RD_VIEW_UI_FUNCTION_DEF(color_rgba) { Temp scratch = scratch_begin(0, 0); Vec2F32 dim = dim_2f32(rect); F32 padding = ui_top_font_size()*3.f; - E_Eval eval = e_eval_from_string(scratch.arena, string); Vec4F32 rgba = {0}; // TODO(rjf): @cfg rd_rgba_from_eval_params(eval, params); Vec4F32 hsva = hsva_from_rgba(rgba); @@ -6127,7 +5801,7 @@ EV_EXPAND_RULE_INFO_FUNCTION_DEF(geo3d) return info; } -RD_VIEW_RULE_UI_FUNCTION_DEF(geo3d) +RD_VIEW_UI_FUNCTION_DEF(geo3d) { Temp scratch = scratch_begin(0, 0); GEO_Scope *geo_scope = geo_scope_open(); @@ -6146,7 +5820,6 @@ RD_VIEW_RULE_UI_FUNCTION_DEF(geo3d) ////////////////////////////// //- rjf: evaluate & unpack expression // - E_Eval eval = e_eval_from_string(scratch.arena, string); U64 base_offset = rd_base_offset_from_eval(eval); Rng1U64 idxs_range = r1u64(base_offset, base_offset+count*sizeof(U32)); Rng1U64 vtxs_range = r1u64(vtx_base_off, vtx_base_off+vtx_size); diff --git a/src/raddbg/raddbg_views.h b/src/raddbg/raddbg_views.h index 36744ed0..c3f22abd 100644 --- a/src/raddbg/raddbg_views.h +++ b/src/raddbg/raddbg_views.h @@ -235,4 +235,19 @@ internal void rd_watch_view_column_release(RD_WatchViewState *wv, RD_WatchViewCo internal void rd_watch_view_init(RD_WatchViewState *ewv); internal void rd_watch_view_build(RD_WatchViewState *ewv, Rng2F32 rect); +//////////////////////////////// +//~ rjf: View Hooks + +// TODO(rjf): @cfg eliminate once we are predeclaring these with metacode + +RD_VIEW_UI_FUNCTION_DEF(null); +RD_VIEW_UI_FUNCTION_DEF(watch); +RD_VIEW_UI_FUNCTION_DEF(text); +RD_VIEW_UI_FUNCTION_DEF(disasm); +RD_VIEW_UI_FUNCTION_DEF(memory); +RD_VIEW_UI_FUNCTION_DEF(bitmap); +RD_VIEW_UI_FUNCTION_DEF(checkbox); +RD_VIEW_UI_FUNCTION_DEF(color_rgba); +RD_VIEW_UI_FUNCTION_DEF(geo3d); + #endif // RADDBG_VIEWS_H