From 05da5ef05778d0653685a20e9e5847b221a54f59 Mon Sep 17 00:00:00 2001 From: Mosder Date: Thu, 23 Jul 2026 13:59:15 +0200 Subject: refactor: generalized command parsing and moved it into a separate file --- analyzer/commands.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++ analyzer/commands.h | 30 ++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 analyzer/commands.c create mode 100644 analyzer/commands.h (limited to 'analyzer') diff --git a/analyzer/commands.c b/analyzer/commands.c new file mode 100644 index 0000000..cb3cdea --- /dev/null +++ b/analyzer/commands.c @@ -0,0 +1,99 @@ +#include "commands.h" + +#include +#include + +#include "analyzer.h" +#include "capture.h" +#include "utils/memory.h" + +#define PROGRAM_NAME "branal" +#define INDENT " " +#define MAX_COMMAND_LENGTH 100 + +// calculate the longest command length to align explenations +int longest_command_length() { + int longest_len = 0; + for (size_t i = 0; i < commands_count; i++) { + Command cmd = commands[i]; + int len = strlen(PROGRAM_NAME); + len += strlen(" ( | ) "); + len += strlen(cmd.short_name) + strlen(cmd.name); + len += strlen(cmd.args_str) == 0 ? 0 : strlen(cmd.args_str) + 1; + if (len > longest_len) + longest_len = len; + } + return longest_len; +} + +// help command handler +int print_help(int argc, char *argv[]) { + int len = longest_command_length(); + + printf("A bare-bones analyzer for the game Broken Ranks\n"); + printf("\nUsage:\n"); + printf(INDENT "%-*s- same as below\n", len, PROGRAM_NAME); + + for (size_t i = 0; i < commands_count; i++) { + Command cmd = commands[i]; + + char buffer[MAX_COMMAND_LENGTH]; + sprintf(buffer, PROGRAM_NAME " (%s | %s) ", cmd.short_name, cmd.name); + if (strlen(cmd.args_str)) + strcat(buffer, cmd.args_str); + + printf(INDENT "%-*s- %s\n", len, buffer, cmd.explanation[0]); + for (size_t j = 1; j < cmd.explanation_lines; j++) { + printf(INDENT "%*s%s\n", len + 2, "", cmd.explanation[j]); + } + } + + return 0; +} + +// live analyzer command handler +int live_anal(int argc, char *argv[]) { + // TODO: implement + printf("Not implemented\n"); + return 1; +} + +// capturing mode command handler +int capture(int argc, char *argv[]) { + capturing_mode(argc >= 3 ? argv[2] : NULL); + return 0; +} + +// file analysis command handler +int file_anal(int argc, char *argv[]) { + if (argc < 3) { + printf("You need to provide a file (or files) to analyze"); + return 1; + } + + for (size_t i = 2; i < argc; i++) { + printf("FILE: %s\n", argv[i]); + analyze_file(argv[i]); + printf("\n"); + } + + return 0; +} + +const Command help_command = {"help", "h", "", {"display this help"}, 1, print_help}; +const Command commands[] = { + {"live", "l", "", {"start live analysis"}, 1, live_anal}, + {"capture", "c", "[file]", {"start capturing packers to file", "If file isn't provided - captures to: $HOME/.local/share/branal/captures"}, 2, capture}, + {"file", "f", "", {"analyze the specified file(s)"}, 1, file_anal}, + help_command +}; +const size_t commands_count = ARR_LEN(commands); + +int is_command(Command command, char *str) { + return !strcmp(command.short_name, str) || !strcmp(command.name, str); +} + +void command_not_recognized() { + printf("Command not recognized\n"); + printf("Use \"%s (%s | %s)\" for help\n", PROGRAM_NAME, help_command.short_name, help_command.name); +} diff --git a/analyzer/commands.h b/analyzer/commands.h new file mode 100644 index 0000000..f53a140 --- /dev/null +++ b/analyzer/commands.h @@ -0,0 +1,30 @@ +// commands.h +// commands to use in the program + +#include + +#define MAX_EXPLANATION_LINES 3 + +typedef struct { + char *name; + char *short_name; + char *args_str; + char *explanation[MAX_EXPLANATION_LINES]; + size_t explanation_lines; + int (*handler)(int argc, char *argv[]); +} Command; + +// all commands of the program +extern const Command commands[]; +extern const size_t commands_count; + +// check if the given command is represented by the given string +// params: +// - command - potentailly represented command +// - str - potentially representing string +// returns: +// 1 if command is represneted by string, 0 if not +extern int is_command(Command command, char *str); + +// print information about help when program didn't recognize command +extern void command_not_recognized(); -- cgit v1.2.3