internal void print_help(const char *argv0) { fprintf(stderr, "rntviewer v" V_MAJOR "." V_MINOR " by silverweed" "\n" "\nUsage: %s [-t] [-s START] [-l LEN] [-w WIDTH] " "\n\t-t: no graphics, output to terminal" "\n\t-s: set first displayed byte to START" "\n\t-l: display LEN bytes (only in terminal mode)" "\n\t-w: display WIDTH bytes per column" "\n" , argv0); } struct Cmdline_Args { b8 print_to_terminal; b8 show_help_and_exit; u64 start_addr; u64 nbytes_displayed; u16 n_cols; String8 ntpl_name; String8 file_name; }; struct Conv_Res { u64 num; b8 error; }; internal Conv_Res str_to_u64(String8 s) { Conv_Res res {}; if (s.size > 2 && s[0] == '0' && s[1] == 'x') { // hexadecimal for (u64 i = 2; i < s.size; ++i) { u8 c = s.str[i]; if (c >= '0' && c <= '9') { res.num *= 16; res.num += c - '0'; } else if (c >= 'A' && c <= 'F') { res.num *= 16; res.num += 10 + c - 'A'; } else if (c >= 'a' && c <= 'f') { res.num *= 16; res.num += 10 + c - 'a'; } else { res.error = true; break; } } } else { // decimal for (u64 i = 0; i < s.size; ++i) { u8 c = s.str[i]; if (c >= '0' && c <= '9') { res.num *= 10; res.num += c - '0'; } else { res.error = true; break; } } } return res; } internal void parse_int_arg(i32 &cur_arg_idx, i32 argc, char **argv, u64 &out) { const char *arg = argv[cur_arg_idx]; if (cur_arg_idx < argc - 1) { String8 nxt_arg = str8_from_c(argv[++cur_arg_idx]); Conv_Res res = str_to_u64(nxt_arg); if (res.error) fprintf(stderr, "Invalid integer after %s flag.\n", arg); else out = res.num; } else { fprintf(stderr, "Argument required after %s flag.\n", arg); } } internal Cmdline_Args parse_args(i32 argc, char **argv) { Cmdline_Args args {}; if (argc < 3) { args.show_help_and_exit = true; return args; } // TODO: refactor this probably for (i32 i = 1; i < argc; ++i) { String8 arg = str8_from_c(argv[i]); if (arg.str[0] == '-') { if (arg.size == 2) { if (arg.str[1] == 't') args.print_to_terminal = true; else if (arg.str[1] == 's') parse_int_arg(i, argc, argv, args.start_addr); else if (arg.str[1] == 'l') parse_int_arg(i, argc, argv, args.nbytes_displayed); else if (arg.str[1] == 'w') { u64 n_cols = 0; parse_int_arg(i, argc, argv, n_cols); args.n_cols = (u16)n_cols; } else args.show_help_and_exit = true; } else { args.show_help_and_exit = true; } } else if (args.ntpl_name.size) { if (args.file_name.size) args.show_help_and_exit = true; else args.file_name = arg; } else { args.ntpl_name = arg; } } return args; }