reorder top-level frame structure; frontend gets chance first

This commit is contained in:
Ryan Fleury
2024-09-08 14:28:06 -07:00
parent dfe0c17b89
commit 8831781af4
2 changed files with 560 additions and 600 deletions
-452
View File
@@ -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, &params, 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, &params, 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, &params, 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: