mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 15:42:23 -07:00
229 lines
6.5 KiB
C
229 lines
6.5 KiB
C
// Copyright (c) Epic Games Tools
|
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
|
|
|
////////////////////////////////
|
|
//~ rjf: Command Line Parsing Functions
|
|
|
|
internal CmdLineOpt **
|
|
cmd_line_slot_from_string(CmdLine *cmd_line, String8 string)
|
|
{
|
|
CmdLineOpt **slot = 0;
|
|
if(cmd_line->option_table_size != 0)
|
|
{
|
|
U64 hash = u64_hash_from_str8(string);
|
|
U64 bucket = hash % cmd_line->option_table_size;
|
|
slot = &cmd_line->option_table[bucket];
|
|
}
|
|
return slot;
|
|
}
|
|
|
|
internal CmdLineOpt *
|
|
cmd_line_opt_from_slot(CmdLineOpt **slot, String8 string)
|
|
{
|
|
CmdLineOpt *result = 0;
|
|
for(CmdLineOpt *var = *slot; var; var = var->hash_next)
|
|
{
|
|
if(str8_match(string, var->string, 0))
|
|
{
|
|
result = var;
|
|
break;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal void
|
|
cmd_line_push_opt(CmdLineOptList *list, CmdLineOpt *var)
|
|
{
|
|
SLLQueuePush(list->first, list->last, var);
|
|
list->count += 1;
|
|
}
|
|
|
|
internal CmdLineOpt *
|
|
cmd_line_insert_opt(Arena *arena, CmdLine *cmd_line, String8 string, String8List values)
|
|
{
|
|
CmdLineOpt *var = 0;
|
|
CmdLineOpt **slot = cmd_line_slot_from_string(cmd_line, string);
|
|
CmdLineOpt *existing_var = cmd_line_opt_from_slot(slot, string);
|
|
if(existing_var != 0)
|
|
{
|
|
var = existing_var;
|
|
}
|
|
else
|
|
{
|
|
var = push_array(arena, CmdLineOpt, 1);
|
|
var->hash_next = *slot;
|
|
var->hash = u64_hash_from_str8(string);
|
|
var->string = push_str8_copy(arena, string);
|
|
var->value_strings = values;
|
|
StringJoin join = {0};
|
|
join.pre = str8_lit("");
|
|
join.sep = str8_lit(",");
|
|
join.post = str8_lit("");
|
|
var->value_string = str8_list_join(arena, &var->value_strings, &join);
|
|
*slot = var;
|
|
cmd_line_push_opt(&cmd_line->options, var);
|
|
}
|
|
return var;
|
|
}
|
|
|
|
internal CmdLine
|
|
cmd_line_from_string_list(Arena *arena, String8List command_line)
|
|
{
|
|
CmdLine parsed = {0};
|
|
parsed.exe_name = command_line.first->string;
|
|
parsed.option_table_size = 64;
|
|
parsed.option_table = push_array(arena, CmdLineOpt *, parsed.option_table_size);
|
|
|
|
//- rjf: parse options / inputs
|
|
B32 after_passthrough_option = 0;
|
|
B32 first_passthrough = 1;
|
|
for(String8Node *node = command_line.first->next, *next = 0; node != 0; node = next)
|
|
{
|
|
next = node->next;
|
|
|
|
//- rjf: look at --, -, or / (only on Windows) at the start of an
|
|
// argument to determine if it's a flag option. all arguments after a
|
|
// single "--" (with no trailing string on the command line will be
|
|
// considered as passthrough input strings.
|
|
B32 is_option = 0;
|
|
String8 option_name = node->string;
|
|
if(!after_passthrough_option)
|
|
{
|
|
is_option = 1;
|
|
if(str8_match(node->string, str8_lit("--"), 0))
|
|
{
|
|
after_passthrough_option = 1;
|
|
is_option = 0;
|
|
}
|
|
else if(str8_match(str8_prefix(node->string, 2), str8_lit("--"), 0))
|
|
{
|
|
option_name = str8_skip(option_name, 2);
|
|
}
|
|
else if(str8_match(str8_prefix(node->string, 1), str8_lit("-"), 0))
|
|
{
|
|
option_name = str8_skip(option_name, 1);
|
|
}
|
|
else if(operating_system_from_context() == OperatingSystem_Windows &&
|
|
str8_match(str8_prefix(node->string, 1), str8_lit("/"), 0))
|
|
{
|
|
option_name = str8_skip(option_name, 1);
|
|
}
|
|
else
|
|
{
|
|
is_option = 0;
|
|
}
|
|
}
|
|
|
|
//- rjf: string is an option
|
|
if(is_option)
|
|
{
|
|
// rjf: unpack option prefix
|
|
B32 has_values = 0;
|
|
U64 value_signifier_position1 = str8_find_needle(option_name, 0, str8_lit(":"), 0);
|
|
U64 value_signifier_position2 = str8_find_needle(option_name, 0, str8_lit("="), 0);
|
|
U64 value_signifier_position = Min(value_signifier_position1, value_signifier_position2);
|
|
String8 value_portion_this_string = str8_skip(option_name, value_signifier_position+1);
|
|
if(value_signifier_position < option_name.size)
|
|
{
|
|
has_values = 1;
|
|
}
|
|
option_name = str8_prefix(option_name, value_signifier_position);
|
|
|
|
// rjf: parse option's values
|
|
String8List values = {0};
|
|
if(has_values)
|
|
{
|
|
for(String8Node *n = node; n; n = n->next)
|
|
{
|
|
next = n->next;
|
|
String8 string = n->string;
|
|
if(n == node)
|
|
{
|
|
string = value_portion_this_string;
|
|
}
|
|
U8 splits[] = { ',' };
|
|
String8List values_in_this_string = str8_split(arena, string, splits, ArrayCount(splits), 0);
|
|
for(String8Node *sub_val = values_in_this_string.first; sub_val; sub_val = sub_val->next)
|
|
{
|
|
str8_list_push(arena, &values, sub_val->string);
|
|
}
|
|
if(!str8_match(str8_postfix(n->string, 1), str8_lit(","), 0) &&
|
|
(n != node || value_portion_this_string.size != 0))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// rjf: store
|
|
cmd_line_insert_opt(arena, &parsed, option_name, values);
|
|
}
|
|
|
|
//- rjf: default path - treat as a passthrough input
|
|
else if(!str8_match(node->string, str8_lit("--"), 0) || !first_passthrough)
|
|
{
|
|
str8_list_push(arena, &parsed.inputs, node->string);
|
|
first_passthrough = 0;
|
|
}
|
|
}
|
|
|
|
//- rjf: fill argc/argv
|
|
parsed.argc = command_line.node_count;
|
|
parsed.argv = push_array(arena, char *, parsed.argc);
|
|
{
|
|
U64 idx = 0;
|
|
for(String8Node *n = command_line.first; n != 0; n = n->next)
|
|
{
|
|
parsed.argv[idx] = (char *)push_str8_copy(arena, n->string).str;
|
|
idx += 1;
|
|
}
|
|
}
|
|
|
|
return parsed;
|
|
}
|
|
|
|
internal CmdLineOpt *
|
|
cmd_line_opt_from_string(CmdLine *cmd_line, String8 name)
|
|
{
|
|
return cmd_line_opt_from_slot(cmd_line_slot_from_string(cmd_line, name), name);
|
|
}
|
|
|
|
internal String8List
|
|
cmd_line_strings(CmdLine *cmd_line, String8 name)
|
|
{
|
|
String8List result = {0};
|
|
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
|
if(var != 0)
|
|
{
|
|
result = var->value_strings;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal String8
|
|
cmd_line_string(CmdLine *cmd_line, String8 name)
|
|
{
|
|
String8 result = {0};
|
|
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
|
if(var != 0)
|
|
{
|
|
result = var->value_string;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
internal B32
|
|
cmd_line_has_flag(CmdLine *cmd_line, String8 name)
|
|
{
|
|
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
|
return (var != 0);
|
|
}
|
|
|
|
internal B32
|
|
cmd_line_has_argument(CmdLine *cmd_line, String8 name)
|
|
{
|
|
CmdLineOpt *var = cmd_line_opt_from_string(cmd_line, name);
|
|
return (var != 0 && var->value_strings.node_count > 0);
|
|
}
|