diff --git a/src/base/base_strings.c b/src/base/base_strings.c index f213187b..dffc8da4 100644 --- a/src/base/base_strings.c +++ b/src/base/base_strings.c @@ -1565,6 +1565,64 @@ string_from_elapsed_time(Arena *arena, DateTime dt){ return(result); } +//////////////////////////////// +//~ rjf: Textual String Wrapping + +internal String8List +wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent) +{ + String8List list = {0}; + Rng1U64 line_range = r1u64(0, 0); + U64 wrapped_indent_level = 0; + static char *spaces = " "; + for (U64 idx = 0; idx <= string.size; idx += 1){ + U8 chr = idx < string.size ? string.str[idx] : 0; + if (chr == '\n'){ + Rng1U64 candidate_line_range = line_range; + candidate_line_range.max = idx; + // NOTE(nick): when wrapping is interrupted with \n we emit a string without including \n + // because later tool_fprint_list inserts separator after each node + // except for last node, so don't strip last \n. + if (idx + 1 == string.size){ + candidate_line_range.max += 1; + } + String8 substr = str8_substr(string, candidate_line_range); + str8_list_push(arena, &list, substr); + line_range = r1u64(idx+1,idx+1); + } + else + if (char_is_space(chr) || chr == 0){ + Rng1U64 candidate_line_range = line_range; + candidate_line_range.max = idx; + String8 substr = str8_substr(string, candidate_line_range); + U64 width_this_line = max_width-wrapped_indent_level; + if (list.node_count == 0){ + width_this_line = first_line_max_width; + } + if (substr.size > width_this_line){ + String8 line = str8_substr(string, line_range); + if (wrapped_indent_level > 0){ + line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); + } + str8_list_push(arena, &list, line); + line_range = r1u64(line_range.max+1, candidate_line_range.max); + wrapped_indent_level = ClampTop(64, wrap_indent); + } + else{ + line_range = candidate_line_range; + } + } + } + if (line_range.min < string.size && line_range.max > line_range.min){ + String8 line = str8_substr(string, line_range); + if (wrapped_indent_level > 0){ + line = push_str8f(arena, "%.*s%S", wrapped_indent_level, spaces, line); + } + str8_list_push(arena, &list, line); + } + return list; +} + //////////////////////////////// //~ rjf: String <-> Color diff --git a/src/base/base_strings.h b/src/base/base_strings.h index cfce641e..e4261089 100644 --- a/src/base/base_strings.h +++ b/src/base/base_strings.h @@ -326,6 +326,11 @@ internal String8 push_date_time_string(Arena *arena, DateTime *date_time); internal String8 push_file_name_date_time_string(Arena *arena, DateTime *date_time); internal String8 string_from_elapsed_time(Arena *arena, DateTime dt); +//////////////////////////////// +//~ rjf: Textual String Wrapping + +internal String8List wrapped_lines_from_string(Arena *arena, String8 string, U64 first_line_max_width, U64 max_width, U64 wrap_indent); + //////////////////////////////// //~ rjf: String <-> Color diff --git a/src/breakpad_from_pdb/breakpad_from_pdb_main.c b/src/breakpad_from_pdb/breakpad_from_pdb_main.c index 64df40c2..09adf58c 100644 --- a/src/breakpad_from_pdb/breakpad_from_pdb_main.c +++ b/src/breakpad_from_pdb/breakpad_from_pdb_main.c @@ -197,16 +197,36 @@ entry_point(CmdLine *cmdline) { //- rjf: initialize state, unpack command line Arena *arena = arena_alloc(); + B32 do_help = (cmd_line_has_flag(cmdline, str8_lit("help")) || + cmd_line_has_flag(cmdline, str8_lit("h")) || + cmd_line_has_flag(cmdline, str8_lit("?"))); P2R_User2Convert *user2convert = p2r_user2convert_from_cmdln(arena, cmdline); user2convert->flags &= ~(P2R_ConvertFlag_Types|P2R_ConvertFlag_UDTs); - //- rjf: display errors with input - if(user2convert->errors.node_count > 0) + //- rjf: display help + if(do_help || user2convert->errors.node_count != 0) { - for(String8Node *n = user2convert->errors.first; n != 0; n = n->next) + fprintf(stderr, "--- breakpad_from_pdb ---------------------------------------------------------\n\n"); + + fprintf(stderr, "This utility converts debug information from PDBs into the textual Breakpad\n"); + fprintf(stderr, "symbol information format, used for various external utilities. The following\n"); + fprintf(stderr, "arguments are accepted:\n\n"); + + fprintf(stderr, "--exe: [optional] Specifies the path of the executable file for which the\n"); + fprintf(stderr, " debug info was generated.\n"); + fprintf(stderr, "--pdb: Specifies the path of the PDB debug info file to\n"); + fprintf(stderr, " convert.\n"); + fprintf(stderr, "--out: Specifies the path at which the output Breakpad debug\n"); + fprintf(stderr, " info will be written.\n\n"); + + if(!do_help) { - fprintf(stderr, "error(input): %.*s\n", str8_varg(n->string)); + for(String8Node *n = user2convert->errors.first; n != 0; n = n->next) + { + fprintf(stderr, "error(input): %.*s\n", str8_varg(n->string)); + } } + os_exit_process(0); } //- rjf: convert diff --git a/src/raddbgi_from_pdb/raddbgi_from_pdb_main.c b/src/raddbgi_from_pdb/raddbgi_from_pdb_main.c index b44b8657..f553a268 100644 --- a/src/raddbgi_from_pdb/raddbgi_from_pdb_main.c +++ b/src/raddbgi_from_pdb/raddbgi_from_pdb_main.c @@ -52,15 +52,34 @@ entry_point(CmdLine *cmdline) { //- rjf: initialize state, unpack command line Arena *arena = arena_alloc(); + B32 do_help = (cmd_line_has_flag(cmdline, str8_lit("help")) || + cmd_line_has_flag(cmdline, str8_lit("h")) || + cmd_line_has_flag(cmdline, str8_lit("?"))); P2R_User2Convert *user2convert = p2r_user2convert_from_cmdln(arena, cmdline); - //- rjf: display errors with input - if(user2convert->errors.node_count > 0) + //- rjf: display help + if(do_help || user2convert->errors.node_count != 0) { - for(String8Node *n = user2convert->errors.first; n != 0; n = n->next) + fprintf(stderr, "--- raddbgi_from_pdb ----------------------------------------------------------\n\n"); + + fprintf(stderr, "This utility converts debug information from PDBs into the RAD Debug Info.\n"); + fprintf(stderr, "format. The following arguments are accepted:\n\n"); + + fprintf(stderr, "--exe: [optional] Specifies the path of the executable file for which the\n"); + fprintf(stderr, " debug info was generated.\n"); + fprintf(stderr, "--pdb: Specifies the path of the PDB debug info file to\n"); + fprintf(stderr, " convert.\n"); + fprintf(stderr, "--out: Specifies the path at which the output Breakpad debug\n"); + fprintf(stderr, " info will be written.\n\n"); + + if(!do_help) { - fprintf(stderr, "error(input): %.*s\n", str8_varg(n->string)); + for(String8Node *n = user2convert->errors.first; n != 0; n = n->next) + { + fprintf(stderr, "error(input): %.*s\n", str8_varg(n->string)); + } } + os_exit_process(0); } //- rjf: convert