mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-09 19:11:38 -07:00
fix top-level frontend exit logic; eliminate path -> entity code, since we are totally off filesystem entities
This commit is contained in:
@@ -729,8 +729,9 @@ ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: bump counter
|
||||
// rjf: bump counters
|
||||
store->entity_kind_counts[kind] += 1;
|
||||
store->entity_kind_alloc_gens[kind] += 1;
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -1287,203 +1287,6 @@ d_entity_equip_namef(D_Entity *entity, char *fmt, ...)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//- rjf: params tree equipment
|
||||
|
||||
internal void
|
||||
d_entity_equip_params(D_Entity *entity, MD_Node *params)
|
||||
{
|
||||
if(entity->params_arena == 0)
|
||||
{
|
||||
entity->params_arena = arena_alloc();
|
||||
}
|
||||
arena_clear(entity->params_arena);
|
||||
entity->params_root = md_tree_copy(entity->params_arena, params);
|
||||
}
|
||||
|
||||
internal void
|
||||
d_entity_equip_param(D_Entity *entity, String8 key, String8 value)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
//- rjf: try to incrementally add to existing tree
|
||||
B32 incrementally_added = 0;
|
||||
if(!md_node_is_nil(entity->params_root))
|
||||
{
|
||||
MD_Node *params = entity->params_root;
|
||||
MD_Node *key_node = md_child_from_string(params, key, 0);
|
||||
if(md_node_is_nil(key_node))
|
||||
{
|
||||
String8 key_copy = push_str8_copy(entity->params_arena, key);
|
||||
key_node = md_push_node(entity->params_arena, MD_NodeKind_Main, MD_NodeFlag_Identifier, key_copy, key_copy, 0);
|
||||
md_node_push_child(params, key_node);
|
||||
String8 value_copy = push_str8_copy(entity->params_arena, value);
|
||||
MD_TokenizeResult value_tokenize = md_tokenize_from_text(scratch.arena, value_copy);
|
||||
MD_ParseResult value_parse = md_parse_from_text_tokens(scratch.arena, str8_zero(), value_copy, value_tokenize.tokens);
|
||||
for(MD_EachNode(child, value_parse.root->first))
|
||||
{
|
||||
child->parent = key_node;
|
||||
}
|
||||
key_node->first = value_parse.root->first;
|
||||
key_node->last = value_parse.root->last;
|
||||
incrementally_added = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: not incrementally added -> fully rewrite parameter tree
|
||||
if(!incrementally_added)
|
||||
{
|
||||
MD_Node *params = md_tree_copy(scratch.arena, entity->params_root);
|
||||
MD_Node *key_node = md_child_from_string(params, key, 0);
|
||||
if(md_node_is_nil(key_node))
|
||||
{
|
||||
key_node = md_push_node(scratch.arena, MD_NodeKind_Main, MD_NodeFlag_Identifier, key, key, 0);
|
||||
md_node_push_child(params, key_node);
|
||||
}
|
||||
MD_TokenizeResult value_tokenize = md_tokenize_from_text(scratch.arena, value);
|
||||
MD_ParseResult value_parse = md_parse_from_text_tokens(scratch.arena, str8_zero(), value, value_tokenize.tokens);
|
||||
for(MD_EachNode(child, value_parse.root->first))
|
||||
{
|
||||
child->parent = key_node;
|
||||
}
|
||||
key_node->first = value_parse.root->first;
|
||||
key_node->last = value_parse.root->last;
|
||||
d_entity_equip_params(entity, params);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//- rjf: opening folders/files & maintaining the entity model of the filesystem
|
||||
|
||||
internal D_Entity *
|
||||
d_entity_from_path(String8 path, D_EntityFromPathFlags flags)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
PathStyle path_style = PathStyle_Relative;
|
||||
String8List path_parts = path_normalized_list_from_string(scratch.arena, path, &path_style);
|
||||
StringMatchFlags path_match_flags = path_match_flags_from_os(operating_system_from_context());
|
||||
|
||||
//- rjf: pass 1: open parts, ignore overrides
|
||||
D_Entity *file_no_override = &d_nil_entity;
|
||||
{
|
||||
D_Entity *parent = d_entity_root();
|
||||
for(String8Node *path_part_n = path_parts.first;
|
||||
path_part_n != 0;
|
||||
path_part_n = path_part_n->next)
|
||||
{
|
||||
// rjf: find next child
|
||||
D_Entity *next_parent = &d_nil_entity;
|
||||
for(D_Entity *child = parent->first; !d_entity_is_nil(child); child = child->next)
|
||||
{
|
||||
B32 name_matches = str8_match(child->string, path_part_n->string, path_match_flags);
|
||||
if(name_matches && child->kind == D_EntityKind_File)
|
||||
{
|
||||
next_parent = child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: no next -> allocate one
|
||||
if(d_entity_is_nil(next_parent))
|
||||
{
|
||||
if(flags & D_EntityFromPathFlag_OpenAsNeeded)
|
||||
{
|
||||
String8 parent_path = d_full_path_from_entity(scratch.arena, parent);
|
||||
String8 path = push_str8f(scratch.arena, "%S%s%S", parent_path, parent_path.size != 0 ? "/" : "", path_part_n->string);
|
||||
FileProperties file_properties = os_properties_from_file_path(path);
|
||||
if(file_properties.created != 0 || flags & D_EntityFromPathFlag_OpenMissing)
|
||||
{
|
||||
next_parent = d_entity_alloc(parent, D_EntityKind_File);
|
||||
d_entity_equip_name(next_parent, path_part_n->string);
|
||||
next_parent->timestamp = file_properties.modified;
|
||||
next_parent->flags |= D_EntityFlag_IsFolder * !!(file_properties.flags & FilePropertyFlag_IsFolder);
|
||||
next_parent->flags |= D_EntityFlag_IsMissing * !!(file_properties.created == 0);
|
||||
if(path_part_n->next != 0)
|
||||
{
|
||||
next_parent->flags |= D_EntityFlag_IsFolder;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = &d_nil_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: next parent -> follow it
|
||||
parent = next_parent;
|
||||
}
|
||||
file_no_override = (parent != d_entity_root() ? parent : &d_nil_entity);
|
||||
}
|
||||
|
||||
//- rjf: pass 2: follow overrides
|
||||
D_Entity *file_overrides_applied = &d_nil_entity;
|
||||
if(flags & D_EntityFromPathFlag_AllowOverrides)
|
||||
{
|
||||
D_Entity *parent = d_entity_root();
|
||||
for(String8Node *path_part_n = path_parts.first;
|
||||
path_part_n != 0;
|
||||
path_part_n = path_part_n->next)
|
||||
{
|
||||
// rjf: find next child
|
||||
D_Entity *next_parent = &d_nil_entity;
|
||||
for(D_Entity *child = parent->first; !d_entity_is_nil(child); child = child->next)
|
||||
{
|
||||
B32 name_matches = str8_match(child->string, path_part_n->string, path_match_flags);
|
||||
if(name_matches && child->kind == D_EntityKind_File)
|
||||
{
|
||||
next_parent = child;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: no next -> allocate one
|
||||
if(d_entity_is_nil(next_parent))
|
||||
{
|
||||
if(flags & D_EntityFromPathFlag_OpenAsNeeded)
|
||||
{
|
||||
String8 parent_path = d_full_path_from_entity(scratch.arena, parent);
|
||||
String8 path = push_str8f(scratch.arena, "%S%s%S", parent_path, parent_path.size != 0 ? "/" : "", path_part_n->string);
|
||||
FileProperties file_properties = os_properties_from_file_path(path);
|
||||
if(file_properties.created != 0 || flags & D_EntityFromPathFlag_OpenMissing)
|
||||
{
|
||||
next_parent = d_entity_alloc(parent, D_EntityKind_File);
|
||||
d_entity_equip_name(next_parent, path_part_n->string);
|
||||
next_parent->timestamp = file_properties.modified;
|
||||
next_parent->flags |= D_EntityFlag_IsFolder * !!(file_properties.flags & FilePropertyFlag_IsFolder);
|
||||
next_parent->flags |= D_EntityFlag_IsMissing * !!(file_properties.created == 0);
|
||||
if(path_part_n->next != 0)
|
||||
{
|
||||
next_parent->flags |= D_EntityFlag_IsFolder;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = &d_nil_entity;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: next parent -> follow it
|
||||
parent = next_parent;
|
||||
}
|
||||
file_overrides_applied = (parent != d_entity_root() ? parent : &d_nil_entity);;
|
||||
}
|
||||
|
||||
//- rjf: pick & return result
|
||||
D_Entity *result = (flags & D_EntityFromPathFlag_AllowOverrides) ? file_overrides_applied : file_no_override;
|
||||
if(flags & D_EntityFromPathFlag_AllowOverrides &&
|
||||
result == file_overrides_applied &&
|
||||
result->flags & D_EntityFlag_IsMissing)
|
||||
{
|
||||
result = file_no_override;
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: file path map override lookups
|
||||
|
||||
internal String8List
|
||||
|
||||
@@ -873,13 +873,6 @@ internal void d_entity_equip_vaddr(D_Entity *entity, U64 vaddr);
|
||||
internal void d_entity_equip_name(D_Entity *entity, String8 name);
|
||||
internal void d_entity_equip_namef(D_Entity *entity, char *fmt, ...);
|
||||
|
||||
//- rjf: params tree equipment
|
||||
internal void d_entity_equip_params(D_Entity *entity, MD_Node *params);
|
||||
internal void d_entity_equip_param(D_Entity *entity, String8 key, String8 value);
|
||||
|
||||
//- rjf: opening folders/files & maintaining the entity model of the filesystem
|
||||
internal D_Entity *d_entity_from_path(String8 path, D_EntityFromPathFlags flags);
|
||||
|
||||
//- rjf: file path map override lookups
|
||||
internal String8List d_possible_overrides_from_file_path(Arena *arena, String8 file_path);
|
||||
|
||||
|
||||
@@ -8262,17 +8262,31 @@ df_frame(void)
|
||||
//- rjf: exiting
|
||||
case DF_CmdKind_Exit:
|
||||
{
|
||||
// rjf: save
|
||||
// rjf: if control processes are live, but this is not force-confirmed, then
|
||||
// get confirmation from user
|
||||
CTRL_EntityList processes = ctrl_entity_list_from_kind(d_state->ctrl_entity_store, CTRL_EntityKind_Process);
|
||||
UI_Key key = ui_key_from_string(ui_key_zero(), str8_lit("lossy_exit_confirmation"));
|
||||
if(processes.count != 0 && !params->force_confirm && !ui_key_match(df_state->confirm_key, key))
|
||||
{
|
||||
df_state->confirm_key = key;
|
||||
df_state->confirm_active = 1;
|
||||
arena_clear(df_state->confirm_arena);
|
||||
MemoryZeroStruct(&df_state->confirm_cmds);
|
||||
df_state->confirm_title = push_str8f(df_state->confirm_arena, "Are you sure you want to exit?");
|
||||
df_state->confirm_desc = push_str8f(df_state->confirm_arena, "The debugger is still attached to %slive process%s.",
|
||||
processes.count == 1 ? "a " : "",
|
||||
processes.count == 1 ? "" : "es");
|
||||
D_CmdParams p = *params;
|
||||
p.force_confirm = 1;
|
||||
d_cmd_list_push(df_state->confirm_arena, &df_state->confirm_cmds, &p, df_cmd_spec_from_kind(DF_CmdKind_Exit));
|
||||
}
|
||||
|
||||
// rjf: otherwise, actually exit
|
||||
else
|
||||
{
|
||||
df_cmd(DF_CmdKind_WriteUserData);
|
||||
df_cmd(DF_CmdKind_WriteProjectData);
|
||||
df_state->last_window_queued_save = 1;
|
||||
}
|
||||
|
||||
// rjf: close all windows
|
||||
for(DF_Window *window = df_state->first_window; window != 0; window = window->next)
|
||||
{
|
||||
df_cmd(DF_CmdKind_CloseWindow, .window = df_handle_from_window(window));
|
||||
df_state->quit = 1;
|
||||
}
|
||||
}break;
|
||||
|
||||
@@ -8308,40 +8322,13 @@ df_frame(void)
|
||||
DF_Window *ws = df_window_from_handle(params->window);
|
||||
if(ws != 0)
|
||||
{
|
||||
D_EntityList running_processes = d_query_cached_entity_list_with_kind(D_EntityKind_Process);
|
||||
|
||||
// NOTE(rjf): if this is the last window, and targets are running, but
|
||||
// this command is not force-confirmed, then we should query the user
|
||||
// to ensure they want to close the debugger before exiting
|
||||
UI_Key key = ui_key_from_string(ui_key_zero(), str8_lit("lossy_exit_confirmation"));
|
||||
if(!ui_key_match(key, df_state->confirm_key) && running_processes.count != 0 && ws == df_state->first_window && ws == df_state->last_window && !params->force_confirm)
|
||||
// rjf: is this the last window? -> exit
|
||||
if(df_state->first_window == df_state->last_window && df_state->first_window == ws)
|
||||
{
|
||||
df_state->confirm_key = key;
|
||||
df_state->confirm_active = 1;
|
||||
arena_clear(df_state->confirm_arena);
|
||||
MemoryZeroStruct(&df_state->confirm_cmds);
|
||||
df_state->confirm_title = push_str8f(df_state->confirm_arena, "Are you sure you want to exit?");
|
||||
df_state->confirm_desc = push_str8f(df_state->confirm_arena, "The debugger is still attached to %slive process%s.",
|
||||
running_processes.count == 1 ? "a " : "",
|
||||
running_processes.count == 1 ? "" : "es");
|
||||
D_CmdParams p = df_cmd_params_from_window(ws);
|
||||
p.force_confirm = 1;
|
||||
d_cmd_list_push(df_state->confirm_arena, &df_state->confirm_cmds, &p, df_cmd_spec_from_kind(DF_CmdKind_CloseWindow));
|
||||
df_cmd(DF_CmdKind_Exit);
|
||||
}
|
||||
|
||||
// NOTE(rjf): if this is the last window, and it is being closed, then
|
||||
// we need to auto-save, and provide one last chance to process saving
|
||||
// commands. after doing so, we can retry.
|
||||
else if(ws == df_state->first_window && ws == df_state->last_window && df_state->last_window_queued_save == 0)
|
||||
{
|
||||
df_state->last_window_queued_save = 1;
|
||||
df_cmd(DF_CmdKind_WriteUserData);
|
||||
df_cmd(DF_CmdKind_WriteProjectData);
|
||||
df_cmd(DF_CmdKind_CloseWindow, .force_confirm = 1, .window = df_handle_from_window(ws));
|
||||
}
|
||||
|
||||
// NOTE(rjf): if this is the last window and we've queued the final autosave,
|
||||
// or if it's not the last window, then we're free to release everything.
|
||||
// rjf: not the last window? -> just release this window
|
||||
else
|
||||
{
|
||||
// NOTE(rjf): we need to explicitly release all panel views, because views
|
||||
@@ -10637,6 +10624,7 @@ df_frame(void)
|
||||
}
|
||||
|
||||
// rjf: try to resolve name as a file
|
||||
#if 0 // TODO(rjf): @msgs
|
||||
D_Entity *file = &d_nil_entity;
|
||||
if(name_resolved == 0)
|
||||
{
|
||||
@@ -10725,6 +10713,7 @@ df_frame(void)
|
||||
}
|
||||
name_resolved = !d_entity_is_nil(file) && !(file->flags & D_EntityFlag_IsMissing) && !(file->flags & D_EntityFlag_IsFolder);
|
||||
}
|
||||
#endif
|
||||
|
||||
// rjf: process resolved info
|
||||
if(name_resolved == 0)
|
||||
@@ -10759,6 +10748,7 @@ df_frame(void)
|
||||
}
|
||||
|
||||
// rjf: name resolved to a file
|
||||
#if 0 // TODO(rjf): @msgs
|
||||
if(name_resolved != 0 && !d_entity_is_nil(file))
|
||||
{
|
||||
String8 path = d_full_path_from_entity(scratch.arena, file);
|
||||
@@ -10767,6 +10757,7 @@ df_frame(void)
|
||||
p.text_point = txt_pt(1, 1);
|
||||
df_push_cmd(df_cmd_spec_from_kind(DF_CmdKind_FindCodeLocation), &p);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user