diff --git a/src/dbg_engine/dbg_engine_core.c b/src/dbg_engine/dbg_engine_core.c index 3eab2aee..fcc211c5 100644 --- a/src/dbg_engine/dbg_engine_core.c +++ b/src/dbg_engine/dbg_engine_core.c @@ -6675,14 +6675,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, DI_ } } - ////////////////////////////// - //- rjf: clear root level commands - // - { - arena_clear(d_state->root_cmd_arena); - MemoryZeroStruct(&d_state->root_cmds); - } - ////////////////////////////// //- rjf: autosave // @@ -6741,20 +6733,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, DI_ { default:{}break; - //- rjf: command fast paths - case D_CmdKind_RunCommand: - { - D_CmdSpec *spec = params.cmd_spec; - if(spec != cmd->spec && !d_cmd_spec_is_nil(spec)) - { - d_cmd_spec_counter_inc(spec); - if(!(spec->info.query.flags & D_CmdQueryFlag_Required)) - { - d_cmd_list_push(arena, cmds, ¶ms, spec); - } - } - }break; - //- rjf: low-level target control operations case D_CmdKind_LaunchAndRun: case D_CmdKind_LaunchAndInit: @@ -7265,436 +7243,6 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, DI_ d_state->current_path = push_str8_copy(d_state->current_path_arena, params.file_path); }break; - //- rjf: config path saving/loading/applying - case D_CmdKind_OpenRecentProject: - { - D_Entity *entity = d_entity_from_handle(params.entity); - if(entity->kind == D_EntityKind_RecentProject) - { - D_CmdParams p = d_cmd_params_zero(); - p.file_path = entity->string; - d_cmd_list_push(arena, cmds, &p, d_cmd_spec_from_kind(D_CmdKind_OpenProject)); - } - }break; - case D_CmdKind_OpenUser: - case D_CmdKind_OpenProject: - { - B32 load_cfg[D_CfgSrc_COUNT] = {0}; - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - load_cfg[src] = (core_cmd_kind == d_cfg_src_load_cmd_kind_table[src]); - } - - //- rjf: normalize path - String8 new_path = path_normalized_from_string(scratch.arena, params.file_path); - - //- rjf: path -> data - FileProperties props = {0}; - String8 data = {0}; - { - OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, new_path); - props = os_properties_from_file(file); - data = os_string_from_file_range(scratch.arena, file, r1u64(0, props.size)); - os_file_close(file); - } - - //- rjf: investigate file path/data - B32 file_is_okay = 1; - if(props.modified != 0 && data.size != 0 && !str8_match(str8_prefix(data, 9), str8_lit("// raddbg"), 0)) - { - file_is_okay = 0; - } - - //- rjf: set new config paths - if(file_is_okay) - { - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - if(load_cfg[src]) - { - arena_clear(d_state->cfg_path_arenas[src]); - d_state->cfg_paths[src] = push_str8_copy(d_state->cfg_path_arenas[src], new_path); - } - } - } - - //- rjf: get config file properties - FileProperties cfg_props[D_CfgSrc_COUNT] = {0}; - if(file_is_okay) - { - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - String8 path = d_cfg_path_from_src(src); - cfg_props[src] = os_properties_from_file_path(path); - } - } - - //- rjf: load files - String8 cfg_data[D_CfgSrc_COUNT] = {0}; - U64 cfg_timestamps[D_CfgSrc_COUNT] = {0}; - if(file_is_okay) - { - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - String8 path = d_cfg_path_from_src(src); - OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, path); - FileProperties props = os_properties_from_file(file); - String8 data = os_string_from_file_range(scratch.arena, file, r1u64(0, props.size)); - if(data.size != 0) - { - cfg_data[src] = data; - cfg_timestamps[src] = props.modified; - } - os_file_close(file); - } - } - - //- rjf: determine if we need to save config - B32 cfg_save[D_CfgSrc_COUNT] = {0}; - if(file_is_okay) - { - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - cfg_save[src] = (load_cfg[src] && cfg_props[src].created == 0); - } - } - - //- rjf: determine if we need to reload config - B32 cfg_load[D_CfgSrc_COUNT] = {0}; - B32 cfg_load_any = 0; - if(file_is_okay) - { - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - cfg_load[src] = (load_cfg[src] && ((cfg_save[src] == 0 && d_state->cfg_cached_timestamp[src] != cfg_timestamps[src]) || cfg_props[src].created == 0)); - cfg_load_any = cfg_load_any || cfg_load[src]; - } - } - - //- rjf: load => build new config table - if(cfg_load_any) - { - arena_clear(d_state->cfg_arena); - MemoryZeroStruct(&d_state->cfg_table); - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - d_cfg_table_push_unparsed_string(d_state->cfg_arena, &d_state->cfg_table, cfg_data[src], src); - } - } - - //- rjf: load => dispatch apply - // - // NOTE(rjf): must happen before `save`. we need to create a default before saving, which - // occurs in the 'apply' path. - // - if(file_is_okay) - { - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - if(cfg_load[src]) - { - D_CmdKind cmd_kind = d_cfg_src_apply_cmd_kind_table[src]; - D_CmdParams params = d_cmd_params_zero(); - d_cmd_list_push(arena, cmds, ¶ms, d_cmd_spec_from_kind(cmd_kind)); - d_state->cfg_cached_timestamp[src] = cfg_timestamps[src]; - } - } - } - - //- rjf: save => dispatch write - if(file_is_okay) - { - for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) - { - if(cfg_save[src]) - { - D_CmdKind cmd_kind = d_cfg_src_write_cmd_kind_table[src]; - D_CmdParams params = d_cmd_params_zero(); - d_cmd_list_push(arena, cmds, ¶ms, d_cmd_spec_from_kind(cmd_kind)); - } - } - } - - //- rjf: bad file -> alert user - if(!file_is_okay) - { - D_CmdParams p = params; - p.string = push_str8f(scratch.arena, "\"%S\" appears to refer to an existing file which is not a RADDBG config file. This would overwrite the file.", new_path); - d_cmd_list_push(arena, cmds, &p, d_cmd_spec_from_kind(D_CmdKind_Error)); - } - }break; - - //- rjf: loading/applying stateful config changes - case D_CmdKind_ApplyUserData: - case D_CmdKind_ApplyProjectData: - { - D_CfgTable *table = d_cfg_table(); - - //- rjf: get config source - D_CfgSrc src = D_CfgSrc_User; - for(D_CfgSrc s = (D_CfgSrc)0; s < D_CfgSrc_COUNT; s = (D_CfgSrc)(s+1)) - { - if(core_cmd_kind == d_cfg_src_apply_cmd_kind_table[s]) - { - src = s; - break; - } - } - - //- rjf: get paths - String8 cfg_path = d_cfg_path_from_src(src); - String8 cfg_folder = str8_chop_last_slash(cfg_path); - - //- rjf: keep track of recent projects - if(src == D_CfgSrc_Project) - { - D_EntityList recent_projects = d_query_cached_entity_list_with_kind(D_EntityKind_RecentProject); - D_Entity *recent_project = &d_nil_entity; - for(D_EntityNode *n = recent_projects.first; n != 0; n = n->next) - { - if(path_match_normalized(cfg_path, n->entity->string)) - { - recent_project = n->entity; - break; - } - } - if(d_entity_is_nil(recent_project)) - { - recent_project = d_entity_alloc(d_entity_root(), D_EntityKind_RecentProject); - d_entity_equip_name(recent_project, path_normalized_from_string(scratch.arena, cfg_path)); - d_entity_equip_cfg_src(recent_project, D_CfgSrc_User); - } - } - - //- rjf: eliminate all existing entities which are derived from config - { - for(EachEnumVal(D_EntityKind, k)) - { - D_EntityKindFlags k_flags = d_entity_kind_flags_table[k]; - if(k_flags & D_EntityKindFlag_IsSerializedToConfig) - { - D_EntityList entities = d_query_cached_entity_list_with_kind(k); - for(D_EntityNode *n = entities.first; n != 0; n = n->next) - { - if(n->entity->cfg_src == src) - { - d_entity_mark_for_deletion(n->entity); - } - } - } - } - } - - //- rjf: apply all entities - { - for(EachEnumVal(D_EntityKind, k)) - { - D_EntityKindFlags k_flags = d_entity_kind_flags_table[k]; - if(k_flags & D_EntityKindFlag_IsSerializedToConfig) - { - D_CfgVal *k_val = d_cfg_val_from_string(table, d_entity_kind_name_lower_table[k]); - for(D_CfgTree *k_tree = k_val->first; - k_tree != &d_nil_cfg_tree; - k_tree = k_tree->next) - { - if(k_tree->source != src) - { - continue; - } - D_Entity *entity = d_entity_alloc(d_entity_root(), k); - d_entity_equip_cfg_src(entity, k_tree->source); - - // rjf: iterate config tree - typedef struct Task Task; - struct Task - { - Task *next; - D_Entity *entity; - MD_Node *n; - }; - Task start_task = {0, entity, k_tree->root}; - Task *first_task = &start_task; - Task *last_task = first_task; - for(Task *t = first_task; t != 0; t = t->next) - { - MD_Node *node = t->n; - for(MD_EachNode(child, node->first)) - { - // rjf: standalone string literals under an entity -> name - if(child->flags & MD_NodeFlag_StringLiteral && child->first == &md_nil_node) - { - String8 string = d_cfg_raw_from_escaped_string(scratch.arena, child->string); - if(d_entity_kind_flags_table[t->entity->kind] & D_EntityKindFlag_NameIsPath) - { - string = path_absolute_dst_from_relative_dst_src(scratch.arena, string, cfg_folder); - } - d_entity_equip_name(t->entity, string); - } - - // rjf: standalone string literals under an entity, with a numeric child -> name & text location - if(child->flags & MD_NodeFlag_StringLiteral && child->first->flags & MD_NodeFlag_Numeric && child->first->first == &md_nil_node) - { - String8 string = d_cfg_raw_from_escaped_string(scratch.arena, child->string); - if(d_entity_kind_flags_table[t->entity->kind] & D_EntityKindFlag_NameIsPath) - { - string = path_absolute_dst_from_relative_dst_src(scratch.arena, string, cfg_folder); - } - d_entity_equip_name(t->entity, string); - S64 line = 0; - try_s64_from_str8_c_rules(child->first->string, &line); - TxtPt pt = txt_pt(line, 1); - d_entity_equip_txt_pt(t->entity, pt); - } - - // rjf: standalone hex literals under an entity -> vaddr - if(child->flags & MD_NodeFlag_Numeric && child->first == &md_nil_node && str8_match(str8_substr(child->string, r1u64(0, 2)), str8_lit("0x"), 0)) - { - U64 vaddr = 0; - try_u64_from_str8_c_rules(child->string, &vaddr); - d_entity_equip_vaddr(t->entity, vaddr); - } - - // rjf: specifically named entity equipment - if((str8_match(child->string, str8_lit("name"), StringMatchFlag_CaseInsensitive) || - str8_match(child->string, str8_lit("label"), StringMatchFlag_CaseInsensitive)) && - child->first != &md_nil_node) - { - String8 string = d_cfg_raw_from_escaped_string(scratch.arena, child->first->string); - if(d_entity_kind_flags_table[t->entity->kind] & D_EntityKindFlag_NameIsPath) - { - string = path_absolute_dst_from_relative_dst_src(scratch.arena, string, cfg_folder); - } - d_entity_equip_name(t->entity, string); - } - if((str8_match(child->string, str8_lit("active"), StringMatchFlag_CaseInsensitive) || - str8_match(child->string, str8_lit("enabled"), StringMatchFlag_CaseInsensitive)) && - child->first != &md_nil_node) - { - d_entity_equip_disabled(t->entity, !str8_match(child->first->string, str8_lit("1"), 0)); - } - if(str8_match(child->string, str8_lit("disabled"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) - { - d_entity_equip_disabled(t->entity, str8_match(child->first->string, str8_lit("1"), 0)); - } - if(str8_match(child->string, str8_lit("hsva"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) - { - Vec4F32 hsva = {0}; - hsva.x = (F32)f64_from_str8(child->first->string); - hsva.y = (F32)f64_from_str8(child->first->next->string); - hsva.z = (F32)f64_from_str8(child->first->next->next->string); - hsva.w = (F32)f64_from_str8(child->first->next->next->next->string); - d_entity_equip_color_hsva(t->entity, hsva); - } - if(str8_match(child->string, str8_lit("color"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) - { - Vec4F32 rgba = rgba_from_hex_string_4f32(child->first->string); - Vec4F32 hsva = hsva_from_rgba(rgba); - d_entity_equip_color_hsva(t->entity, hsva); - } - if(str8_match(child->string, str8_lit("line"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) - { - S64 line = 0; - try_s64_from_str8_c_rules(child->first->string, &line); - TxtPt pt = txt_pt(line, 1); - d_entity_equip_txt_pt(t->entity, pt); - } - if((str8_match(child->string, str8_lit("vaddr"), StringMatchFlag_CaseInsensitive) || - str8_match(child->string, str8_lit("addr"), StringMatchFlag_CaseInsensitive)) && - child->first != &md_nil_node) - { - U64 vaddr = 0; - try_u64_from_str8_c_rules(child->first->string, &vaddr); - d_entity_equip_vaddr(t->entity, vaddr); - } - - // rjf: sub-entity -> create new task - D_EntityKind sub_entity_kind = D_EntityKind_Nil; - for(EachEnumVal(D_EntityKind, k2)) - { - if(child->flags & MD_NodeFlag_Identifier && child->first != &md_nil_node && - (str8_match(child->string, d_entity_kind_name_lower_table[k2], StringMatchFlag_CaseInsensitive) || - (k2 == D_EntityKind_Executable && str8_match(child->string, str8_lit("exe"), StringMatchFlag_CaseInsensitive)))) - { - Task *task = push_array(scratch.arena, Task, 1); - task->next = t->next; - task->entity = d_entity_alloc(t->entity, k2); - task->n = child; - t->next = task; - break; - } - } - } - } - } - } - } - } - - //- rjf: apply exception code filters - D_CfgVal *filter_tables = d_cfg_val_from_string(table, str8_lit("exception_code_filters")); - for(D_CfgTree *table = filter_tables->first; - table != &d_nil_cfg_tree; - table = table->next) - { - for(MD_EachNode(rule, table->root->first)) - { - String8 name = rule->string; - String8 val_string = rule->first->string; - U64 val = 0; - if(try_u64_from_str8_c_rules(val_string, &val)) - { - CTRL_ExceptionCodeKind kind = CTRL_ExceptionCodeKind_Null; - for(CTRL_ExceptionCodeKind k = (CTRL_ExceptionCodeKind)(CTRL_ExceptionCodeKind_Null+1); - k < CTRL_ExceptionCodeKind_COUNT; - k = (CTRL_ExceptionCodeKind)(k+1)) - { - if(str8_match(name, ctrl_exception_code_kind_lowercase_code_string_table[k], 0)) - { - kind = k; - break; - } - } - if(kind != CTRL_ExceptionCodeKind_Null) - { - if(val) - { - d_state->ctrl_exception_code_filters[kind/64] |= (1ull<<(kind%64)); - } - else - { - d_state->ctrl_exception_code_filters[kind/64] &= ~(1ull<<(kind%64)); - } - } - } - } - } - }break; - - //- rjf: writing config changes - case D_CmdKind_WriteUserData: - case D_CmdKind_WriteProjectData: - { - D_CfgSrc src = D_CfgSrc_User; - for(D_CfgSrc s = (D_CfgSrc)0; s < D_CfgSrc_COUNT; s = (D_CfgSrc)(s+1)) - { - if(core_cmd_kind == d_cfg_src_write_cmd_kind_table[s]) - { - src = s; - break; - } - } - arena_clear(d_state->cfg_write_arenas[src]); - MemoryZeroStruct(&d_state->cfg_write_data[src]); - String8 path = d_cfg_path_from_src(src); - String8List strs = d_cfg_strings_from_core(scratch.arena, path, src); - String8 header = push_str8f(scratch.arena, "// raddbg %s file\n\n", d_cfg_src_string_table[src].str); - str8_list_push_front(scratch.arena, &strs, header); - String8 data = str8_list_join(scratch.arena, &strs, 0); - String8 data_indented = indented_from_string(scratch.arena, data); - d_state->cfg_write_issued[src] = 1; - d_cfg_push_write_string(src, data_indented); - }break; - //- rjf: override file links case D_CmdKind_SetFileOverrideLinkSrc: case D_CmdKind_SetFileOverrideLinkDst: diff --git a/src/dbg_frontend/dbg_frontend_core.c b/src/dbg_frontend/dbg_frontend_core.c index d87906d1..3d9868c1 100644 --- a/src/dbg_frontend/dbg_frontend_core.c +++ b/src/dbg_frontend/dbg_frontend_core.c @@ -8188,63 +8188,13 @@ df_frame(void) D_CmdList cmds = d_gather_root_cmds(scratch.arena); ////////////////////////////// - //- rjf: gather targets + //- rjf: clear root level commands // - D_TargetArray targets = {0}; { - D_EntityList target_entities = d_query_cached_entity_list_with_kind(D_EntityKind_Target); - targets.count = target_entities.count; - targets.v = push_array(scratch.arena, D_Target, targets.count); - U64 idx = 0; - for(D_EntityNode *n = target_entities.first; n != 0; n = n->next, idx += 1) - { - D_Entity *src_target = n->entity; - D_Entity *src_target_exe = d_entity_child_from_kind(src_target, D_EntityKind_Target); - D_Entity *src_target_args = d_entity_child_from_kind(src_target, D_EntityKind_Arguments); - D_Entity *src_target_wdir = d_entity_child_from_kind(src_target, D_EntityKind_WorkingDirectory); - D_Entity *src_target_entry = d_entity_child_from_kind(src_target, D_EntityKind_EntryPoint); - D_Target *dst_target = &targets.v[idx]; - dst_target->exe = src_target_exe->string; - dst_target->args = src_target_args->string; - dst_target->working_directory = src_target_wdir->string; - dst_target->custom_entry_point_name = src_target_entry->string; - } + arena_clear(d_state->root_cmd_arena); + MemoryZeroStruct(&d_state->root_cmds); } - ////////////////////////////// - //- rjf: gather breakpoints - // - D_BreakpointArray breakpoints = {0}; - { - D_EntityList bp_entities = d_query_cached_entity_list_with_kind(D_EntityKind_Breakpoint); - breakpoints.count = bp_entities.count; - breakpoints.v = push_array(scratch.arena, D_Breakpoint, breakpoints.count); - U64 idx = 0; - for(D_EntityNode *n = bp_entities.first; n != 0; n = n->next) - { - D_Entity *src_bp = n->entity; - if(src_bp->disabled) - { - breakpoints.count -= 1; - continue; - } - D_Entity *src_bp_loc = d_entity_child_from_kind(src_bp, D_EntityKind_Location); - D_Entity *src_bp_cnd = d_entity_child_from_kind(src_bp, D_EntityKind_Condition); - D_Breakpoint *dst_bp = &breakpoints.v[idx]; - dst_bp->file_path = src_bp_loc->string; - dst_bp->pt = src_bp_loc->text_point; - dst_bp->symbol_name = src_bp_loc->string; - dst_bp->vaddr = src_bp_loc->vaddr; - dst_bp->condition = src_bp_cnd->string; - idx += 1; - } - } - - ////////////////////////////// - //- rjf: tick debug engine - // - d_tick(scratch.arena, &targets, &breakpoints, di_scope, &cmds, dt); - ////////////////////////////// //- rjf: unpack eval-dependent info // @@ -8438,96 +8388,11 @@ df_frame(void) } e_select_interpret_ctx(interpret_ctx); - ////////////////////////////// - //- rjf: apply new rich hover info - // - arena_clear(df_state->rich_hover_info_current_arena); - MemoryCopyStruct(&df_state->rich_hover_info_current, &df_state->rich_hover_info_next); - df_state->rich_hover_info_current.dbgi_key = di_key_copy(df_state->rich_hover_info_current_arena, &df_state->rich_hover_info_current.dbgi_key); - arena_clear(df_state->rich_hover_info_next_arena); - MemoryZeroStruct(&df_state->rich_hover_info_next); - - ////////////////////////////// - //- rjf: animate confirmation - // - { - F32 rate = df_setting_val_from_code(DF_SettingCode_MenuAnimations).s32 ? 1 - pow_f32(2, (-10.f * d_dt())) : 1.f; - B32 confirm_open = df_state->confirm_active; - df_state->confirm_t += rate * ((F32)!!confirm_open-df_state->confirm_t); - if(abs_f32(df_state->confirm_t - (F32)!!confirm_open) > 0.005f) - { - df_request_frame(); - } - } - - ////////////////////////////// - //- rjf: animate theme - // - { - DF_Theme *current = &df_state->cfg_theme; - DF_Theme *target = &df_state->cfg_theme_target; - F32 rate = 1 - pow_f32(2, (-50.f * d_dt())); - for(DF_ThemeColor color = DF_ThemeColor_Null; - color < DF_ThemeColor_COUNT; - color = (DF_ThemeColor)(color+1)) - { - if(abs_f32(target->colors[color].x - current->colors[color].x) > 0.01f || - abs_f32(target->colors[color].y - current->colors[color].y) > 0.01f || - abs_f32(target->colors[color].z - current->colors[color].z) > 0.01f || - abs_f32(target->colors[color].w - current->colors[color].w) > 0.01f) - { - df_request_frame(); - } - current->colors[color].x += (target->colors[color].x - current->colors[color].x) * rate; - current->colors[color].y += (target->colors[color].y - current->colors[color].y) * rate; - current->colors[color].z += (target->colors[color].z - current->colors[color].z) * rate; - current->colors[color].w += (target->colors[color].w - current->colors[color].w) * rate; - } - } - - ////////////////////////////// - //- rjf: animate alive-transitions for entities - // - { - F32 rate = 1.f - pow_f32(2.f, -20.f*d_dt()); - for(D_Entity *e = d_entity_root(); !d_entity_is_nil(e); e = d_entity_rec_depth_first_pre(e, d_entity_root()).next) - { - F32 diff = (1.f - e->alive_t); - e->alive_t += diff * rate; - if(diff >= 0.01f) - { - df_request_frame(); - } - } - } - - ////////////////////////////// - //- rjf: capture is active? -> keep rendering - // - if(ProfIsCapturing() || DEV_telemetry_capture) - { - df_request_frame(); - } - - ////////////////////////////// - //- rjf: commit params changes for all views - // - { - for(DF_View *v = df_state->first_view; !df_view_is_nil(v); v = v->alloc_next) - { - if(v->params_write_gen == v->params_read_gen+1) - { - v->params_read_gen += 1; - } - } - } - ////////////////////////////// //- rjf: process top-level graphical commands // B32 panel_reset_done = 0; { - B32 cfg_write_done[D_CfgSrc_COUNT] = {0}; for(D_CmdNode *cmd_node = cmds.first; cmd_node != 0; cmd_node = cmd_node->next) @@ -8565,10 +8430,15 @@ df_frame(void) case D_CmdKind_RunCommand: { D_CmdSpec *spec = params->cmd_spec; + if(!d_cmd_spec_is_nil(spec)) + { + d_cmd_spec_counter_inc(spec); + } // rjf: command simply executes - just no-op in this layer if(!d_cmd_spec_is_nil(spec) && !(spec->info.query.flags & D_CmdQueryFlag_Required)) { + d_cmd_list_push(scratch.arena, &cmds, params, spec); } // rjf: command has required query -> prep query @@ -8725,6 +8595,165 @@ df_frame(void) d_cmd_list_push(scratch.arena, &cmds, params, d_cmd_spec_from_kind(D_CmdKind_FindThread)); }break; + //- rjf: config path saving/loading/applying + case D_CmdKind_OpenRecentProject: + { + D_Entity *entity = d_entity_from_handle(params->entity); + if(entity->kind == D_EntityKind_RecentProject) + { + D_CmdParams p = d_cmd_params_zero(); + p.file_path = entity->string; + d_cmd_list_push(scratch.arena, &cmds, &p, d_cmd_spec_from_kind(D_CmdKind_OpenProject)); + } + }break; + case D_CmdKind_OpenUser: + case D_CmdKind_OpenProject: + { + B32 load_cfg[D_CfgSrc_COUNT] = {0}; + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + load_cfg[src] = (kind == d_cfg_src_load_cmd_kind_table[src]); + } + + //- rjf: normalize path + String8 new_path = path_normalized_from_string(scratch.arena, params->file_path); + + //- rjf: path -> data + FileProperties props = {0}; + String8 data = {0}; + { + OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, new_path); + props = os_properties_from_file(file); + data = os_string_from_file_range(scratch.arena, file, r1u64(0, props.size)); + os_file_close(file); + } + + //- rjf: investigate file path/data + B32 file_is_okay = 1; + if(props.modified != 0 && data.size != 0 && !str8_match(str8_prefix(data, 9), str8_lit("// raddbg"), 0)) + { + file_is_okay = 0; + } + + //- rjf: set new config paths + if(file_is_okay) + { + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + if(load_cfg[src]) + { + arena_clear(d_state->cfg_path_arenas[src]); + d_state->cfg_paths[src] = push_str8_copy(d_state->cfg_path_arenas[src], new_path); + } + } + } + + //- rjf: get config file properties + FileProperties cfg_props[D_CfgSrc_COUNT] = {0}; + if(file_is_okay) + { + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + String8 path = d_cfg_path_from_src(src); + cfg_props[src] = os_properties_from_file_path(path); + } + } + + //- rjf: load files + String8 cfg_data[D_CfgSrc_COUNT] = {0}; + U64 cfg_timestamps[D_CfgSrc_COUNT] = {0}; + if(file_is_okay) + { + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + String8 path = d_cfg_path_from_src(src); + OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, path); + FileProperties props = os_properties_from_file(file); + String8 data = os_string_from_file_range(scratch.arena, file, r1u64(0, props.size)); + if(data.size != 0) + { + cfg_data[src] = data; + cfg_timestamps[src] = props.modified; + } + os_file_close(file); + } + } + + //- rjf: determine if we need to save config + B32 cfg_save[D_CfgSrc_COUNT] = {0}; + if(file_is_okay) + { + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + cfg_save[src] = (load_cfg[src] && cfg_props[src].created == 0); + } + } + + //- rjf: determine if we need to reload config + B32 cfg_load[D_CfgSrc_COUNT] = {0}; + B32 cfg_load_any = 0; + if(file_is_okay) + { + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + cfg_load[src] = (load_cfg[src] && ((cfg_save[src] == 0 && d_state->cfg_cached_timestamp[src] != cfg_timestamps[src]) || cfg_props[src].created == 0)); + cfg_load_any = cfg_load_any || cfg_load[src]; + } + } + + //- rjf: load => build new config table + if(cfg_load_any) + { + arena_clear(d_state->cfg_arena); + MemoryZeroStruct(&d_state->cfg_table); + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + d_cfg_table_push_unparsed_string(d_state->cfg_arena, &d_state->cfg_table, cfg_data[src], src); + } + } + + //- rjf: load => dispatch apply + // + // NOTE(rjf): must happen before `save`. we need to create a default before saving, which + // occurs in the 'apply' path. + // + if(file_is_okay) + { + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + if(cfg_load[src]) + { + D_CmdKind cmd_kind = d_cfg_src_apply_cmd_kind_table[src]; + D_CmdParams params = d_cmd_params_zero(); + d_cmd_list_push(scratch.arena, &cmds, ¶ms, d_cmd_spec_from_kind(cmd_kind)); + d_state->cfg_cached_timestamp[src] = cfg_timestamps[src]; + } + } + } + + //- rjf: save => dispatch write + if(file_is_okay) + { + for(D_CfgSrc src = (D_CfgSrc)0; src < D_CfgSrc_COUNT; src = (D_CfgSrc)(src+1)) + { + if(cfg_save[src]) + { + D_CmdKind cmd_kind = d_cfg_src_write_cmd_kind_table[src]; + D_CmdParams params = d_cmd_params_zero(); + d_cmd_list_push(scratch.arena, &cmds, ¶ms, d_cmd_spec_from_kind(cmd_kind)); + } + } + } + + //- rjf: bad file -> alert user + if(!file_is_okay) + { + D_CmdParams p = *params; + p.string = push_str8f(scratch.arena, "\"%S\" appears to refer to an existing file which is not a RADDBG config file. This would overwrite the file.", new_path); + d_cmd_list_push(scratch.arena, &cmds, &p, d_cmd_spec_from_kind(D_CmdKind_Error)); + } + }break; + //- rjf: loading/applying stateful config changes case D_CmdKind_ApplyUserData: case D_CmdKind_ApplyProjectData: @@ -8732,7 +8761,7 @@ df_frame(void) D_CfgTable *table = d_cfg_table(); OS_HandleArray monitors = os_push_monitors_array(scratch.arena); - //- rjf: get src + //- rjf: get config source D_CfgSrc src = D_CfgSrc_User; for(D_CfgSrc s = (D_CfgSrc)0; s < D_CfgSrc_COUNT; s = (D_CfgSrc)(s+1)) { @@ -8747,6 +8776,230 @@ df_frame(void) String8 cfg_path = d_cfg_path_from_src(src); String8 cfg_folder = str8_chop_last_slash(cfg_path); + //- rjf: keep track of recent projects + if(src == D_CfgSrc_Project) + { + D_EntityList recent_projects = d_query_cached_entity_list_with_kind(D_EntityKind_RecentProject); + D_Entity *recent_project = &d_nil_entity; + for(D_EntityNode *n = recent_projects.first; n != 0; n = n->next) + { + if(path_match_normalized(cfg_path, n->entity->string)) + { + recent_project = n->entity; + break; + } + } + if(d_entity_is_nil(recent_project)) + { + recent_project = d_entity_alloc(d_entity_root(), D_EntityKind_RecentProject); + d_entity_equip_name(recent_project, path_normalized_from_string(scratch.arena, cfg_path)); + d_entity_equip_cfg_src(recent_project, D_CfgSrc_User); + } + } + + //- rjf: eliminate all existing entities which are derived from config + { + for(EachEnumVal(D_EntityKind, k)) + { + D_EntityKindFlags k_flags = d_entity_kind_flags_table[k]; + if(k_flags & D_EntityKindFlag_IsSerializedToConfig) + { + D_EntityList entities = d_query_cached_entity_list_with_kind(k); + for(D_EntityNode *n = entities.first; n != 0; n = n->next) + { + if(n->entity->cfg_src == src) + { + d_entity_mark_for_deletion(n->entity); + } + } + } + } + } + + //- rjf: apply all entities + { + for(EachEnumVal(D_EntityKind, k)) + { + D_EntityKindFlags k_flags = d_entity_kind_flags_table[k]; + if(k_flags & D_EntityKindFlag_IsSerializedToConfig) + { + D_CfgVal *k_val = d_cfg_val_from_string(table, d_entity_kind_name_lower_table[k]); + for(D_CfgTree *k_tree = k_val->first; + k_tree != &d_nil_cfg_tree; + k_tree = k_tree->next) + { + if(k_tree->source != src) + { + continue; + } + D_Entity *entity = d_entity_alloc(d_entity_root(), k); + d_entity_equip_cfg_src(entity, k_tree->source); + + // rjf: iterate config tree + typedef struct Task Task; + struct Task + { + Task *next; + D_Entity *entity; + MD_Node *n; + }; + Task start_task = {0, entity, k_tree->root}; + Task *first_task = &start_task; + Task *last_task = first_task; + for(Task *t = first_task; t != 0; t = t->next) + { + MD_Node *node = t->n; + for(MD_EachNode(child, node->first)) + { + // rjf: standalone string literals under an entity -> name + if(child->flags & MD_NodeFlag_StringLiteral && child->first == &md_nil_node) + { + String8 string = d_cfg_raw_from_escaped_string(scratch.arena, child->string); + if(d_entity_kind_flags_table[t->entity->kind] & D_EntityKindFlag_NameIsPath) + { + string = path_absolute_dst_from_relative_dst_src(scratch.arena, string, cfg_folder); + } + d_entity_equip_name(t->entity, string); + } + + // rjf: standalone string literals under an entity, with a numeric child -> name & text location + if(child->flags & MD_NodeFlag_StringLiteral && child->first->flags & MD_NodeFlag_Numeric && child->first->first == &md_nil_node) + { + String8 string = d_cfg_raw_from_escaped_string(scratch.arena, child->string); + if(d_entity_kind_flags_table[t->entity->kind] & D_EntityKindFlag_NameIsPath) + { + string = path_absolute_dst_from_relative_dst_src(scratch.arena, string, cfg_folder); + } + d_entity_equip_name(t->entity, string); + S64 line = 0; + try_s64_from_str8_c_rules(child->first->string, &line); + TxtPt pt = txt_pt(line, 1); + d_entity_equip_txt_pt(t->entity, pt); + } + + // rjf: standalone hex literals under an entity -> vaddr + if(child->flags & MD_NodeFlag_Numeric && child->first == &md_nil_node && str8_match(str8_substr(child->string, r1u64(0, 2)), str8_lit("0x"), 0)) + { + U64 vaddr = 0; + try_u64_from_str8_c_rules(child->string, &vaddr); + d_entity_equip_vaddr(t->entity, vaddr); + } + + // rjf: specifically named entity equipment + if((str8_match(child->string, str8_lit("name"), StringMatchFlag_CaseInsensitive) || + str8_match(child->string, str8_lit("label"), StringMatchFlag_CaseInsensitive)) && + child->first != &md_nil_node) + { + String8 string = d_cfg_raw_from_escaped_string(scratch.arena, child->first->string); + if(d_entity_kind_flags_table[t->entity->kind] & D_EntityKindFlag_NameIsPath) + { + string = path_absolute_dst_from_relative_dst_src(scratch.arena, string, cfg_folder); + } + d_entity_equip_name(t->entity, string); + } + if((str8_match(child->string, str8_lit("active"), StringMatchFlag_CaseInsensitive) || + str8_match(child->string, str8_lit("enabled"), StringMatchFlag_CaseInsensitive)) && + child->first != &md_nil_node) + { + d_entity_equip_disabled(t->entity, !str8_match(child->first->string, str8_lit("1"), 0)); + } + if(str8_match(child->string, str8_lit("disabled"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) + { + d_entity_equip_disabled(t->entity, str8_match(child->first->string, str8_lit("1"), 0)); + } + if(str8_match(child->string, str8_lit("hsva"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) + { + Vec4F32 hsva = {0}; + hsva.x = (F32)f64_from_str8(child->first->string); + hsva.y = (F32)f64_from_str8(child->first->next->string); + hsva.z = (F32)f64_from_str8(child->first->next->next->string); + hsva.w = (F32)f64_from_str8(child->first->next->next->next->string); + d_entity_equip_color_hsva(t->entity, hsva); + } + if(str8_match(child->string, str8_lit("color"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) + { + Vec4F32 rgba = rgba_from_hex_string_4f32(child->first->string); + Vec4F32 hsva = hsva_from_rgba(rgba); + d_entity_equip_color_hsva(t->entity, hsva); + } + if(str8_match(child->string, str8_lit("line"), StringMatchFlag_CaseInsensitive) && child->first != &md_nil_node) + { + S64 line = 0; + try_s64_from_str8_c_rules(child->first->string, &line); + TxtPt pt = txt_pt(line, 1); + d_entity_equip_txt_pt(t->entity, pt); + } + if((str8_match(child->string, str8_lit("vaddr"), StringMatchFlag_CaseInsensitive) || + str8_match(child->string, str8_lit("addr"), StringMatchFlag_CaseInsensitive)) && + child->first != &md_nil_node) + { + U64 vaddr = 0; + try_u64_from_str8_c_rules(child->first->string, &vaddr); + d_entity_equip_vaddr(t->entity, vaddr); + } + + // rjf: sub-entity -> create new task + D_EntityKind sub_entity_kind = D_EntityKind_Nil; + for(EachEnumVal(D_EntityKind, k2)) + { + if(child->flags & MD_NodeFlag_Identifier && child->first != &md_nil_node && + (str8_match(child->string, d_entity_kind_name_lower_table[k2], StringMatchFlag_CaseInsensitive) || + (k2 == D_EntityKind_Executable && str8_match(child->string, str8_lit("exe"), StringMatchFlag_CaseInsensitive)))) + { + Task *task = push_array(scratch.arena, Task, 1); + task->next = t->next; + task->entity = d_entity_alloc(t->entity, k2); + task->n = child; + t->next = task; + break; + } + } + } + } + } + } + } + } + + //- rjf: apply exception code filters + D_CfgVal *filter_tables = d_cfg_val_from_string(table, str8_lit("exception_code_filters")); + for(D_CfgTree *table = filter_tables->first; + table != &d_nil_cfg_tree; + table = table->next) + { + for(MD_EachNode(rule, table->root->first)) + { + String8 name = rule->string; + String8 val_string = rule->first->string; + U64 val = 0; + if(try_u64_from_str8_c_rules(val_string, &val)) + { + CTRL_ExceptionCodeKind kind = CTRL_ExceptionCodeKind_Null; + for(CTRL_ExceptionCodeKind k = (CTRL_ExceptionCodeKind)(CTRL_ExceptionCodeKind_Null+1); + k < CTRL_ExceptionCodeKind_COUNT; + k = (CTRL_ExceptionCodeKind)(k+1)) + { + if(str8_match(name, ctrl_exception_code_kind_lowercase_code_string_table[k], 0)) + { + kind = k; + break; + } + } + if(kind != CTRL_ExceptionCodeKind_Null) + { + if(val) + { + d_state->ctrl_exception_code_filters[kind/64] |= (1ull<<(kind%64)); + } + else + { + d_state->ctrl_exception_code_filters[kind/64] &= ~(1ull<<(kind%64)); + } + } + } + } + } + //- rjf: eliminate all windows for(DF_Window *window = df_state->first_window; window != 0; window = window->next) { @@ -9383,15 +9636,20 @@ df_frame(void) break; } } - if(cfg_write_done[src] == 0) - { - cfg_write_done[src] = 1; - String8 path = d_cfg_path_from_src(src); - String8List strs = df_cfg_strings_from_gfx(scratch.arena, path, src); - String8 data = str8_list_join(scratch.arena, &strs, 0); - String8 data_indented = indented_from_string(scratch.arena, data); - d_cfg_push_write_string(src, data_indented); - } + arena_clear(d_state->cfg_write_arenas[src]); + MemoryZeroStruct(&d_state->cfg_write_data[src]); + String8 path = d_cfg_path_from_src(src); + String8List d_strs = d_cfg_strings_from_core(scratch.arena, path, src); + String8List df_strs = df_cfg_strings_from_gfx(scratch.arena, path, src); + String8 header = push_str8f(scratch.arena, "// raddbg %s file\n\n", d_cfg_src_string_table[src].str); + String8List strs = {0}; + str8_list_push(scratch.arena, &strs, header); + str8_list_concat_in_place(&strs, &d_strs); + str8_list_concat_in_place(&strs, &df_strs); + String8 data = str8_list_join(scratch.arena, &strs, 0); + String8 data_indented = indented_from_string(scratch.arena, data); + d_state->cfg_write_issued[src] = 1; + d_cfg_push_write_string(src, data_indented); }break; //- rjf: code navigation @@ -11060,6 +11318,160 @@ df_frame(void) } } + ////////////////////////////// + //- rjf: gather targets + // + D_TargetArray targets = {0}; + { + D_EntityList target_entities = d_query_cached_entity_list_with_kind(D_EntityKind_Target); + targets.count = target_entities.count; + targets.v = push_array(scratch.arena, D_Target, targets.count); + U64 idx = 0; + for(D_EntityNode *n = target_entities.first; n != 0; n = n->next, idx += 1) + { + D_Entity *src_target = n->entity; + D_Entity *src_target_exe = d_entity_child_from_kind(src_target, D_EntityKind_Target); + D_Entity *src_target_args = d_entity_child_from_kind(src_target, D_EntityKind_Arguments); + D_Entity *src_target_wdir = d_entity_child_from_kind(src_target, D_EntityKind_WorkingDirectory); + D_Entity *src_target_entry = d_entity_child_from_kind(src_target, D_EntityKind_EntryPoint); + D_Target *dst_target = &targets.v[idx]; + dst_target->exe = src_target_exe->string; + dst_target->args = src_target_args->string; + dst_target->working_directory = src_target_wdir->string; + dst_target->custom_entry_point_name = src_target_entry->string; + } + } + + ////////////////////////////// + //- rjf: gather breakpoints + // + D_BreakpointArray breakpoints = {0}; + { + D_EntityList bp_entities = d_query_cached_entity_list_with_kind(D_EntityKind_Breakpoint); + breakpoints.count = bp_entities.count; + breakpoints.v = push_array(scratch.arena, D_Breakpoint, breakpoints.count); + U64 idx = 0; + for(D_EntityNode *n = bp_entities.first; n != 0; n = n->next) + { + D_Entity *src_bp = n->entity; + if(src_bp->disabled) + { + breakpoints.count -= 1; + continue; + } + D_Entity *src_bp_loc = d_entity_child_from_kind(src_bp, D_EntityKind_Location); + D_Entity *src_bp_cnd = d_entity_child_from_kind(src_bp, D_EntityKind_Condition); + D_Breakpoint *dst_bp = &breakpoints.v[idx]; + dst_bp->file_path = src_bp_loc->string; + dst_bp->pt = src_bp_loc->text_point; + dst_bp->symbol_name = src_bp_loc->string; + dst_bp->vaddr = src_bp_loc->vaddr; + dst_bp->condition = src_bp_cnd->string; + idx += 1; + } + } + + ////////////////////////////// + //- rjf: tick debug engine + // + // TODO(rjf): hacking around for @msgs + D_CmdList more_cmds = d_gather_root_cmds(scratch.arena); + if(cmds.first != 0 && more_cmds.first != 0) + { + cmds.last->next = more_cmds.first; + cmds.last = more_cmds.last; + cmds.count += more_cmds.count; + } + else if(more_cmds.first != 0) + { + MemoryCopyStruct(&cmds, &more_cmds); + } + d_tick(scratch.arena, &targets, &breakpoints, di_scope, &cmds, dt); + + ////////////////////////////// + //- rjf: apply new rich hover info + // + arena_clear(df_state->rich_hover_info_current_arena); + MemoryCopyStruct(&df_state->rich_hover_info_current, &df_state->rich_hover_info_next); + df_state->rich_hover_info_current.dbgi_key = di_key_copy(df_state->rich_hover_info_current_arena, &df_state->rich_hover_info_current.dbgi_key); + arena_clear(df_state->rich_hover_info_next_arena); + MemoryZeroStruct(&df_state->rich_hover_info_next); + + ////////////////////////////// + //- rjf: animate confirmation + // + { + F32 rate = df_setting_val_from_code(DF_SettingCode_MenuAnimations).s32 ? 1 - pow_f32(2, (-10.f * d_dt())) : 1.f; + B32 confirm_open = df_state->confirm_active; + df_state->confirm_t += rate * ((F32)!!confirm_open-df_state->confirm_t); + if(abs_f32(df_state->confirm_t - (F32)!!confirm_open) > 0.005f) + { + df_request_frame(); + } + } + + ////////////////////////////// + //- rjf: animate theme + // + { + DF_Theme *current = &df_state->cfg_theme; + DF_Theme *target = &df_state->cfg_theme_target; + F32 rate = 1 - pow_f32(2, (-50.f * d_dt())); + for(DF_ThemeColor color = DF_ThemeColor_Null; + color < DF_ThemeColor_COUNT; + color = (DF_ThemeColor)(color+1)) + { + if(abs_f32(target->colors[color].x - current->colors[color].x) > 0.01f || + abs_f32(target->colors[color].y - current->colors[color].y) > 0.01f || + abs_f32(target->colors[color].z - current->colors[color].z) > 0.01f || + abs_f32(target->colors[color].w - current->colors[color].w) > 0.01f) + { + df_request_frame(); + } + current->colors[color].x += (target->colors[color].x - current->colors[color].x) * rate; + current->colors[color].y += (target->colors[color].y - current->colors[color].y) * rate; + current->colors[color].z += (target->colors[color].z - current->colors[color].z) * rate; + current->colors[color].w += (target->colors[color].w - current->colors[color].w) * rate; + } + } + + ////////////////////////////// + //- rjf: animate alive-transitions for entities + // + { + F32 rate = 1.f - pow_f32(2.f, -20.f*d_dt()); + for(D_Entity *e = d_entity_root(); !d_entity_is_nil(e); e = d_entity_rec_depth_first_pre(e, d_entity_root()).next) + { + F32 diff = (1.f - e->alive_t); + e->alive_t += diff * rate; + if(diff >= 0.01f) + { + df_request_frame(); + } + } + } + + ////////////////////////////// + //- rjf: capture is active? -> keep rendering + // + if(ProfIsCapturing() || DEV_telemetry_capture) + { + df_request_frame(); + } + + ////////////////////////////// + //- rjf: commit params changes for all views + // + { + for(DF_View *v = df_state->first_view; !df_view_is_nil(v); v = v->alloc_next) + { + if(v->params_write_gen == v->params_read_gen+1) + { + v->params_read_gen += 1; + } + } + } + ////////////////////////////// //- rjf: queue drag drop (TODO(rjf): @msgs) //