diff options
| author | Mel <mel@rnrd.eu> | 2025-07-04 18:58:48 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2025-07-04 18:58:48 +0200 |
| commit | 7817842632f27a8b894de724ecc1df590142455f (patch) | |
| tree | 6331b6752d93854c91fb0cc0b7b44e1615f5349b /boot | |
| parent | 8f2e0f0202317cc27371d2833eb93b64230ac0e8 (diff) | |
| download | catskill-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.c | 185 |
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; + } + } + } } |
