aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-07-04 18:58:48 +0200
committerMel <mel@rnrd.eu>2025-07-04 18:58:48 +0200
commit7817842632f27a8b894de724ecc1df590142455f (patch)
tree6331b6752d93854c91fb0cc0b7b44e1615f5349b /boot
parent8f2e0f0202317cc27371d2833eb93b64230ac0e8 (diff)
downloadcatskill-7817842632f27a8b894de724ecc1df590142455f.tar.zst
catskill-7817842632f27a8b894de724ecc1df590142455f.zip
Argument parser for catboot tool, different command execution
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot')
-rw-r--r--boot/catboot.c185
1 files changed, 168 insertions, 17 deletions
diff --git a/boot/catboot.c b/boot/catboot.c
index a62dc47..e2e5315 100644
--- a/boot/catboot.c
+++ b/boot/catboot.c
@@ -26,7 +26,9 @@
#include "catboot.h"
-const ascii*
+#define VERSION "0.0.0"
+
+struct String
read_file(const ascii* path)
{
struct stat stat_info;
@@ -42,33 +44,59 @@ read_file(const ascii* path)
const unknown* file_data =
mmap(nil, stat_info.st_size, mmap_prot, mmap_flags, file_descriptor, 0);
- return file_data;
+ return string_from_static_c_string(file_data);
}
-int32
-main(const int32 argc, const ascii* argv[])
+void
+usage(void)
{
- if (argc != 2) {
- printf("usage: catboot <filename>\n");
- return EXIT_FAILURE;
- }
- const ascii* file_path = argv[1];
+ fprintf(
+ stderr,
+ "usage:\n"
+ " catboot <filename>\n"
+ " catboot --test-lex <filename>\n"
+ " catboot --test-parse <filename>\n"
+ "\n"
+ "options:\n"
+ " --test-lex <file>\t output token stream for file\n"
+ " --test-parse <file>\t output abstract syntax tree for file in s-expr format\n"
+ " -?, --help\t\t\t print this help message\n"
+ " -v, --version\t\t print current version\n");
+}
- const ascii* source_buffer = read_file(file_path);
- struct String source = string_from_static_c_string(source_buffer);
+void
+version(void)
+{
+ fprintf(
+ stderr,
+ "catboot (catskill), version " VERSION "\n"
+ "\n"
+ "This program's source code is subject to the terms of the Mozilla Public\n"
+ "License, v. 2.0. If a copy of the MPL was not distributed with this\n"
+ "file, You can obtain one at https://mozilla.org/MPL/2.0/.\n"
+ "\n"
+ "Copyright (c) 2025, Mel G. <mel@rnrd.eu>\n");
+}
+integer
+debug_lex_pass(struct String source)
+{
struct Lexer lexer;
lexer_new(&lexer, source);
struct Token token;
- printf("tokens: ");
do {
token = lexer_next(&lexer);
printf("%s ", token_kind_to_string(token.kind));
} while (token.kind != TOKEN_END_OF_FILE);
- printf("\n");
- // reset lexer
+ return 0;
+}
+
+integer
+debug_parse_pass(struct String source)
+{
+ struct Lexer lexer;
lexer_new(&lexer, source);
struct Parser parser;
@@ -77,11 +105,134 @@ main(const int32 argc, const ascii* argv[])
struct Parser_Error parser_error = parser_error_none();
struct Tree tree = parser_do_your_thing(&parser, &parser_error);
if (!parser_error_is_none(&parser_error)) {
- printf("parser error: %s\n", parser_error_to_string(&parser_error));
- return EXIT_FAILURE;
+ fprintf(stderr, "parser error: %s\n", parser_error_to_string(&parser_error));
+ return 1;
}
tree_printer(&tree);
- return EXIT_SUCCESS;
+ return 0;
+}
+
+enum Command_Result
+{
+ COMMAND_OK,
+ COMMAND_FAIL,
+};
+
+struct Command_Arguments
+{
+ const ascii* input;
+};
+
+enum Command_Result
+version_command(struct Command_Arguments* arguments)
+{
+ version();
+ return COMMAND_OK;
+}
+
+enum Command_Result
+help_command(struct Command_Arguments* arguments)
+{
+ usage();
+ return COMMAND_OK;
+}
+
+enum Command_Result
+test_lex_command(struct Command_Arguments* arguments)
+{
+ struct String source = read_file(arguments->input);
+
+ // TODO: lexer errors
+ debug_lex_pass(source);
+
+ return COMMAND_OK;
+}
+
+enum Command_Result
+test_parse_command(struct Command_Arguments* arguments)
+{
+ struct String source = read_file(arguments->input);
+
+ if (debug_parse_pass(source)) return COMMAND_FAIL;
+
+ return COMMAND_OK;
+}
+
+enum Command_Result
+default_command(struct Command_Arguments* arguments)
+{
+ struct String source = read_file(arguments->input);
+
+ debug_lex_pass(source);
+ printf("\n");
+ if (debug_parse_pass(source)) return COMMAND_FAIL;
+ printf("\n");
+
+ return COMMAND_OK;
+}
+
+typedef enum Command_Result (*Command_Function)(struct Command_Arguments*);
+
+struct Command_Definition
+{
+ bool is_default;
+ const ascii* name;
+ const ascii short_name;
+ Command_Function function;
+};
+
+struct Command_Definition command_definitions[] = {
+ { .name = "test-lex", .function = test_lex_command },
+ { .name = "test-parse", .function = test_parse_command },
+ { .name = "version", .short_name = 'v', .function = version_command },
+ { .name = "help", .short_name = '?', .function = help_command },
+
+ { .is_default = true, .function = default_command },
+};
+
+int32
+main(const int32 argc, ascii* argv[])
+{
+ if (argc < 2) {
+ usage();
+ return EXIT_FAILURE;
+ }
+
+ bool have_command = false;
+ ascii *command_name = nil, short_command_name = '\0', *input = nil;
+ for (uint a = 1; a < argc; ++a) {
+ ascii* arg = argv[a];
+
+ if (arg[0] == '-') {
+ check(!have_command, "multiple commands given");
+ if (arg[1] == '-') {
+ check(!command_name, "multiple full-name commands given");
+ command_name = &arg[2];
+ } else {
+ check(!short_command_name, "multiple short-name commands given");
+ short_command_name = arg[1];
+ }
+ have_command = true;
+ } else {
+ check(!input, "multiple inputs given");
+ input = arg;
+ }
+ }
+
+ struct Command_Arguments arguments = { .input = input };
+ for (uint d = 0; d < ARRAY_SIZE(command_definitions); ++d) {
+ struct Command_Definition* definition = &command_definitions[d];
+
+ if (definition->is_default || (command_name && strcmp(definition->name, command_name) == 0)
+ || (short_command_name && definition->short_name == short_command_name)) {
+ switch (definition->function(&arguments)) {
+ case COMMAND_OK:
+ return EXIT_SUCCESS;
+ case COMMAND_FAIL:
+ return EXIT_FAILURE;
+ }
+ }
+ }
}