diff --git a/code/logic/fossil/io/parser.h b/code/logic/fossil/io/parser.h index feaaf9f..2454efe 100644 --- a/code/logic/fossil/io/parser.h +++ b/code/logic/fossil/io/parser.h @@ -22,10 +22,14 @@ extern "C" { // Types of command argument typedef enum { - FOSSIL_IO_PARSER_BOOL, // Boolean (enable/disable) - FOSSIL_IO_PARSER_STRING, // String argument - FOSSIL_IO_PARSER_INT, // Integer argument - FOSSIL_IO_PARSER_COMBO // Combo of predefined values + FOSSIL_IO_PARSER_BOOL, // Boolean (enable/disable) + FOSSIL_IO_PARSER_STRING, // String argument + FOSSIL_IO_PARSER_INT, // Integer argument + FOSSIL_IO_PARSER_FLOAT, // Floating-point argument + FOSSIL_IO_PARSER_DATE, // Date argument + FOSSIL_IO_PARSER_ARRAY, // Array of values + FOSSIL_IO_PARSER_FEATURE, // Feature flag + FOSSIL_IO_PARSER_INVALID // Invalid argument type } fossil_io_parser_arg_type_t; // Structure to represent each argument in the command @@ -54,6 +58,21 @@ typedef struct fossil_io_parser_palette_s { fossil_io_parser_command_t *commands; // List of commands } fossil_io_parser_palette_t; +// ================================================================== +// Global Variables +// ================================================================== + +extern int FOSSIL_CLI_TOGGLE_DRY_RUN; +extern int FOSSIL_CLI_TOGGLE_VERBOSE; +extern int FOSSIL_CLI_TOGGLE_SANITY; + +extern char *FOSSIL_CLI_TOOL_NAME; +extern char *FOSSIL_CLI_TOOL_VERSION; +extern char *FOSSIL_CLI_TOOL_AUTHOR; +extern char *FOSSIL_CLI_TOOL_LICENSE; +extern char *FOSSIL_CLI_TOOL_DESCRIPTION; +extern char *FOSSIL_CLI_TOOL_WEBSITE; + // ================================================================== // Functions // ================================================================== diff --git a/code/logic/parser.c b/code/logic/parser.c index 8d46a50..b474a13 100644 --- a/code/logic/parser.c +++ b/code/logic/parser.c @@ -12,6 +12,7 @@ * ----------------------------------------------------------------------------- */ #include "fossil/io/parser.h" +#include "fossil/io/output.h" #include #include #include @@ -19,6 +20,18 @@ #include #include +int FOSSIL_CLI_TOGGLE_DRY_RUN = 0; +int FOSSIL_CLI_TOGGLE_VERBOSE = 0; +int FOSSIL_CLI_TOGGLE_SANITY = 0; + +char *FOSSIL_CLI_TOOL_NAME = "fossil-cli"; +char *FOSSIL_CLI_TOOL_VERSION = "1.0.0"; +char *FOSSIL_CLI_TOOL_AUTHOR = "Fossil Logic"; +char *FOSSIL_CLI_TOOL_LICENSE = "Mozilla Public License 2.0"; +char *FOSSIL_CLI_TOOL_DESCRIPTION = "A command-line interface for Fossil Logic."; +char *FOSSIL_CLI_TOOL_WEBSITE = "https://fossil-logic.com"; + + extern char *_custom_strdup(const char *str) { if (!str) return NULL; size_t len = strlen(str) + 1; @@ -71,98 +84,223 @@ const char* suggest_command(const char *input, fossil_io_parser_palette_t *palet // Functions // ================================================================== +void show_this(void) { + fossil_io_printf("{blue}About this tool:{reset}\n"); + fossil_io_printf("{cyan} Name:{reset} %s\n", FOSSIL_CLI_TOOL_NAME); + fossil_io_printf("{cyan} Version:{reset} %s\n", FOSSIL_CLI_TOOL_VERSION); + fossil_io_printf("{cyan} Author:{reset} %s\n", FOSSIL_CLI_TOOL_AUTHOR); + fossil_io_printf("{cyan} License:{reset} %s\n", FOSSIL_CLI_TOOL_LICENSE); + fossil_io_printf("{cyan} Description:{reset} %s\n", FOSSIL_CLI_TOOL_DESCRIPTION); + fossil_io_printf("{cyan} Website:{reset} %s\n", FOSSIL_CLI_TOOL_WEBSITE); + + fossil_io_printf("{blue}Operating System:{reset} %s\n", +#if defined(_WIN32) || defined(_WIN64) + "Windows" +#elif defined(__linux__) + "Linux" +#elif defined(__APPLE__) && defined(__MACH__) + "macOS" +#elif defined(__unix__) + "Unix" +#else + "Unknown" +#endif + ); + + fossil_io_printf("{blue}Endianness:{reset} %s\n", +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + "Little Endian" +#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + "Big Endian" +#else + "Unknown" +#endif + ); +} + +void show_version(void) { + fossil_io_printf("{blue}Version:{reset} %s\n", FOSSIL_CLI_TOOL_VERSION); +} + void show_help(const char *command_name, const fossil_io_parser_palette_t *palette) { fossil_io_parser_command_t *command = palette->commands; // If no specific command is provided, show all commands if (!command_name) { - printf("Available commands:\n"); + fossil_io_printf("{blue}Available commands:{reset}\n"); while (command) { - printf(" %s: %s\n", command->name, command->description); + fossil_io_printf("{cyan} %s: %s{reset}\n", command->name, command->description); command = command->next; } - printf("\nUse '--help ' for details on a specific command.\n"); + fossil_io_printf("\n{blue}Use '--help ' for details on a specific command.{reset}\n"); return; } // Search for the specific command while (command) { if (strcmp(command->name, command_name) == 0) { - printf("Command: %s\nDescription: %s\n", command->name, command->description); - printf("Arguments:\n"); + fossil_io_printf("{blue}Command: %s\nDescription: %s{reset}\n", command->name, command->description); + fossil_io_printf("{blue}Arguments:{reset}\n"); fossil_io_parser_argument_t *arg = command->arguments; while (arg) { - printf(" --%s (%s): %s\n", + fossil_io_printf("{cyan} --%s (%s): %s{reset}\n", arg->name, arg->type == FOSSIL_IO_PARSER_BOOL ? "bool" : arg->type == FOSSIL_IO_PARSER_STRING ? "string" : arg->type == FOSSIL_IO_PARSER_INT ? "int" : - "combo", + arg->type == FOSSIL_IO_PARSER_FLOAT ? "float" : + arg->type == FOSSIL_IO_PARSER_DATE ? "date" : + arg->type == FOSSIL_IO_PARSER_ARRAY ? "array" : + arg->type == FOSSIL_IO_PARSER_FEATURE ? "feature" : + arg->type == FOSSIL_IO_PARSER_INVALID ? "invalid" : + "unknown", arg->value ? arg->value : "No default value"); - if (arg->type == FOSSIL_IO_PARSER_COMBO) { - printf(" Options: "); - for (int i = 0; i < arg->combo_count; i++) { - printf("%s%s", arg->combo_options[i], i == arg->combo_count - 1 ? "" : ", "); - } - printf("\n"); - } arg = arg->next; } + + // Handle specific flags + fossil_io_printf("{blue}Built-in:{reset}\n"); + fossil_io_printf("{cyan} --help: Show help information for this command.{reset}\n"); + fossil_io_printf("{cyan} --version: Display the version of the application.{reset}\n"); + fossil_io_printf("{cyan} --this: Perform the operation on the current context.{reset}\n"); + fossil_io_printf("{cyan} --dry-run: Simulate the operation without making changes.{reset}\n"); + fossil_io_printf("{cyan} --verbose: Provide detailed output during execution.{reset}\n"); + fossil_io_printf("{cyan} --sanity: Perform sanity checks before execution.{reset}\n"); return; } command = command->next; } // If the command is not found - fprintf(stderr, "Unknown command '%s'. Use '--help' to see available commands.\n", command_name); + fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown command '%s'. Use '--help' to see available commands.{reset}\n", command_name); } - void show_usage(const char *command_name, const fossil_io_parser_palette_t *palette) { fossil_io_parser_command_t *command = palette->commands; // Search for the specific command while (command) { if (strcmp(command->name, command_name) == 0) { - printf("Usage example for '%s':\n", command->name); - printf(" %s", command->name); + fossil_io_printf("{blue}Usage example for '%s':{reset}\n", command->name); + fossil_io_printf("{cyan} %s{reset}", command->name); fossil_io_parser_argument_t *arg = command->arguments; while (arg) { - printf(" --%s ", arg->name); - if (arg->type == FOSSIL_IO_PARSER_STRING) { - printf(""); - } else if (arg->type == FOSSIL_IO_PARSER_INT) { - printf(""); - } else if (arg->type == FOSSIL_IO_PARSER_BOOL) { - printf(""); - } else if (arg->type == FOSSIL_IO_PARSER_COMBO) { - printf("<%s>", arg->combo_options[0]); // Show first combo option + fossil_io_printf("{cyan} --%s {reset}", arg->name); + switch (arg->type) { + case FOSSIL_IO_PARSER_STRING: + fossil_io_printf("{cyan}{reset}"); + break; + case FOSSIL_IO_PARSER_INT: + fossil_io_printf("{cyan}{reset}"); + break; + case FOSSIL_IO_PARSER_BOOL: + fossil_io_printf("{cyan}{reset}"); + break; + case FOSSIL_IO_PARSER_FLOAT: + fossil_io_printf("{cyan}{reset}"); + break; + case FOSSIL_IO_PARSER_DATE: + fossil_io_printf("{cyan}{reset}"); + break; + case FOSSIL_IO_PARSER_ARRAY: + fossil_io_printf("{cyan}{reset}"); + break; + case FOSSIL_IO_PARSER_FEATURE: + fossil_io_printf("{cyan}{reset}"); + break; + default: + fossil_io_printf("{cyan}{reset}"); + break; } arg = arg->next; } - printf("\n"); + + // Add built-in flags to the usage + fossil_io_printf("{cyan} [--this] [--dry-run] [--verbose] [--sanity] [--version] [--help]{reset}"); + fossil_io_printf("\n"); return; } command = command->next; } // If the command is not found - fprintf(stderr, "Unknown command '%s'. Use '--help' to see available commands.\n", command_name); + fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown command '%s'. Use '--help' to see available commands.{reset}\n", command_name); } fossil_io_parser_palette_t *fossil_io_parser_create_palette(const char *name, const char *description) { + if (!name || !description) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Palette name and description cannot be NULL.{reset}\n"); + return NULL; + } + fossil_io_parser_palette_t *palette = malloc(sizeof(fossil_io_parser_palette_t)); + if (!palette) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for palette.{reset}\n"); + return NULL; + } + palette->name = _custom_strdup(name); + if (!palette->name) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for palette name.{reset}\n"); + free(palette); + return NULL; + } + palette->description = _custom_strdup(description); + if (!palette->description) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for palette description.{reset}\n"); + free(palette->name); + free(palette); + return NULL; + } + palette->commands = NULL; return palette; } fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palette_t *palette, const char *command_name, const char *description) { + if (!palette || !command_name || !description) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Palette, command name, and description cannot be NULL.{reset}\n"); + return NULL; + } + + if (strlen(command_name) == 0) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Command name cannot be empty.{reset}\n"); + return NULL; + } + + // Check for duplicate command name + fossil_io_parser_command_t *current = palette->commands; + while (current) { + if (strcmp(current->name, command_name) == 0) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Command with name '%s' already exists.{reset}\n", command_name); + return NULL; + } + current = current->next; + } + fossil_io_parser_command_t *command = malloc(sizeof(fossil_io_parser_command_t)); + if (!command) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for command.{reset}\n"); + return NULL; + } + command->name = _custom_strdup(command_name); + if (!command->name) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for command name.{reset}\n"); + free(command); + return NULL; + } + command->description = _custom_strdup(description); + if (!command->description) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for command description.{reset}\n"); + free(command->name); + free(command); + return NULL; + } + command->arguments = NULL; command->prev = NULL; command->next = palette->commands; @@ -174,8 +312,30 @@ fossil_io_parser_command_t *fossil_io_parser_add_command(fossil_io_parser_palett } fossil_io_parser_argument_t *fossil_io_parser_add_argument(fossil_io_parser_command_t *command, const char *arg_name, fossil_io_parser_arg_type_t arg_type, char **combo_options, int combo_count) { + if (!command || !arg_name) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Command and argument name cannot be NULL.{reset}\n"); + return NULL; + } + fossil_io_parser_argument_t *argument = malloc(sizeof(fossil_io_parser_argument_t)); + if (!argument) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for argument.{reset}\n"); + return NULL; + } + argument->name = _custom_strdup(arg_name); + if (!argument->name) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for argument name.{reset}\n"); + free(argument); + return NULL; + } + + if (arg_type < FOSSIL_IO_PARSER_BOOL || arg_type > FOSSIL_IO_PARSER_FEATURE) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Invalid argument type for '%s'.{reset}\n", arg_name); + free(argument->name); + free(argument); + return NULL; + } argument->type = arg_type; argument->value = NULL; argument->combo_options = combo_options; @@ -185,34 +345,86 @@ fossil_io_parser_argument_t *fossil_io_parser_add_argument(fossil_io_parser_comm return argument; } -// Updated parse function +// Updated parse function with error checking void fossil_io_parser_parse(fossil_io_parser_palette_t *palette, int argc, char **argv) { + if (!palette || !argv) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Invalid arguments passed to parser.{reset}\n"); + return; + } + if (argc < 2) { - fprintf(stderr, "No command provided.\n"); + fossil_io_fprintf(FOSSIL_STDERR, "{red}No command provided.{reset}\n"); return; } - const char *command_name = argv[1]; + const char *command_name = NULL; + int global_flags_processed = 0; - // Check for --help and --usage flags - if (strcmp(argv[1], "--help") == 0) { - if (argc == 3) { - show_help(argv[2], palette); // Show help for a specific command - } else { - show_help(NULL, palette); // Show general help + // Scan for global flags and commands + for (int i = 1; i < argc; i++) { + const char *arg = argv[i]; + + if (!arg) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: NULL argument encountered.{reset}\n"); + return; + } + + if (strcmp(arg, "--help") == 0) { + if (i + 1 < argc && argv[i + 1][0] != '-') { + show_help(argv[++i], palette); // Show help for a specific command + } else { + show_help(NULL, palette); // Show general help + } + global_flags_processed = 1; + break; + } + + if (strcmp(arg, "--version") == 0) { + show_version(); + global_flags_processed = 1; + break; + } + + if (strcmp(arg, "--this") == 0) { + show_this(); + global_flags_processed = 1; + break; + } + + if (strcmp(arg, "--dry-run") == 0) { + FOSSIL_CLI_TOGGLE_DRY_RUN = 1; + fossil_io_printf("{blue}Dry-run mode enabled.{reset}\n"); + continue; } + + if (strcmp(arg, "--verbose") == 0) { + FOSSIL_CLI_TOGGLE_VERBOSE = 1; + fossil_io_printf("{blue}Verbose mode enabled.{reset}\n"); + continue; + } + + if (strcmp(arg, "--sanity") == 0) { + FOSSIL_CLI_TOGGLE_SANITY = 1; + fossil_io_printf("{blue}Sanity checks enabled.{reset}\n"); + continue; + } + + // Assume the first non-flag argument is the command + if (arg[0] != '-' && !command_name) { + command_name = arg; + } + } + + if (global_flags_processed) { return; } - if (strcmp(argv[1], "--usage") == 0) { - if (argc == 3) { - show_usage(argv[2], palette); // Show usage for a specific command - } else { - fprintf(stderr, "Usage: --usage \n"); - } + if (!command_name) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}No command provided. Type '--help' to see available commands.{reset}\n"); return; } + // Process specific commands fossil_io_parser_command_t *command = palette->commands; while (command) { if (strcmp(command->name, command_name) == 0) { @@ -225,47 +437,155 @@ void fossil_io_parser_parse(fossil_io_parser_palette_t *palette, int argc, char // Suggest a similar command or show an error const char *suggestion = suggest_command(command_name, palette); if (suggestion) { - fprintf(stderr, "Unknown command: '%s'. Did you mean '%s'?\n", command_name, suggestion); + fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown command: '%s'. Did you mean '%s'?{reset}\n", command_name, suggestion); } else { - fprintf(stderr, "Unknown command: '%s'. Type '--help' to see available commands.\n", command_name); + fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown command: '%s'. Type '--help' to see available commands.{reset}\n", command_name); } return; } // Process command arguments - for (int i = 2; i < argc; i++) { + for (int i = 1; i < argc; i++) { const char *arg_value = argv[i]; + if (!arg_value) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: NULL argument encountered.{reset}\n"); + return; + } + + if (arg_value[0] == '-') { + continue; // Skip flags already processed + } + fossil_io_parser_argument_t *argument = command->arguments; while (argument) { if (strcmp(argument->name, arg_value) == 0) { switch (argument->type) { case FOSSIL_IO_PARSER_BOOL: argument->value = malloc(sizeof(int)); - if (strcmp(arg_value, "enable") == 0) { + if (!argument->value) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for boolean argument.{reset}\n"); + return; + } + if (i + 1 < argc && (strcmp(argv[i + 1], "true") == 0 || strcmp(argv[i + 1], "yes") == 0)) { *(int *)argument->value = 1; // Enable - } else if (strcmp(arg_value, "disable") == 0) { + i++; + } else if (i + 1 < argc && (strcmp(argv[i + 1], "false") == 0 || strcmp(argv[i + 1], "no") == 0)) { *(int *)argument->value = 0; // Disable + i++; } else { - fprintf(stderr, "Invalid value for boolean argument: %s\n", arg_value); + fossil_io_fprintf(FOSSIL_STDERR, "{red}Invalid value for boolean argument: %s{reset}\n", argv[i + 1]); free(argument->value); argument->value = NULL; } break; case FOSSIL_IO_PARSER_STRING: - argument->value = _custom_strdup(arg_value); // Custom _custom_strdup + if (i + 1 < argc) { + argument->value = _custom_strdup(argv[++i]); + if (!argument->value) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for string argument.{reset}\n"); + return; + } + } else { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for string argument: %s{reset}\n", arg_value); + } break; case FOSSIL_IO_PARSER_INT: - argument->value = malloc(sizeof(int)); - *(int *)argument->value = atoi(arg_value); + if (i + 1 < argc) { + argument->value = malloc(sizeof(int)); + if (!argument->value) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for integer argument.{reset}\n"); + return; + } + *(int *)argument->value = atoi(argv[++i]); + } else { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for integer argument: %s{reset}\n", arg_value); + } + break; + case FOSSIL_IO_PARSER_FLOAT: + if (i + 1 < argc) { + argument->value = malloc(sizeof(float)); + if (!argument->value) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for float argument.{reset}\n"); + return; + } + *(float *)argument->value = atof(argv[++i]); + } else { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for float argument: %s{reset}\n", arg_value); + } + break; + case FOSSIL_IO_PARSER_DATE: + if (i + 1 < argc) { + argument->value = _custom_strdup(argv[++i]); + if (!argument->value) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for date argument.{reset}\n"); + return; + } + } else { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for date argument: %s{reset}\n", arg_value); + } break; - case FOSSIL_IO_PARSER_COMBO: - for (int j = 0; j < argument->combo_count; j++) { - if (strcmp(arg_value, argument->combo_options[j]) == 0) { - argument->value = _custom_strdup(arg_value); - break; + case FOSSIL_IO_PARSER_ARRAY: { + if (i + 1 < argc) { + char *array_copy = _custom_strdup(argv[++i]); + if (!array_copy) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for array argument.{reset}\n"); + return; + } + char *token = strtok(array_copy, ","); + char **array_values = NULL; + int count = 0; + + while (token) { + char **temp = realloc(array_values, sizeof(char *) * (count + 1)); + if (!temp) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for array values.{reset}\n"); + free(array_copy); + for (int j = 0; j < count; j++) { + free(array_values[j]); + } + free(array_values); + return; + } + array_values = temp; + array_values[count++] = _custom_strdup(token); + token = strtok(NULL, ","); } + + argument->value = (char *)array_values; + free(array_copy); + } else { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for array argument: %s{reset}\n", arg_value); } break; + } + case FOSSIL_IO_PARSER_FEATURE: + if (i + 1 < argc) { + argument->value = malloc(sizeof(int)); + if (!argument->value) { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Error: Memory allocation failed for feature argument.{reset}\n"); + return; + } + if (strcmp(argv[i + 1], "enable") == 0) { + *(int *)argument->value = 1; // Enable + i++; + } else if (strcmp(argv[i + 1], "disable") == 0) { + *(int *)argument->value = 0; // Disable + i++; + } else if (strcmp(argv[i + 1], "auto") == 0) { + *(int *)argument->value = 2; // Auto + i++; + } else { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Invalid value for feature argument: %s{reset}\n", argv[i + 1]); + free(argument->value); + argument->value = NULL; + } + } else { + fossil_io_fprintf(FOSSIL_STDERR, "{red}Missing value for feature argument: %s{reset}\n", arg_value); + } + break; + default: + fossil_io_fprintf(FOSSIL_STDERR, "{red}Unknown argument type for: %s{reset}\n", arg_value); + break; } break; } @@ -279,11 +599,10 @@ void fossil_io_parser_free(fossil_io_parser_palette_t *palette) { while (command) { fossil_io_parser_argument_t *argument = command->arguments; while (argument) { - if (argument->type == FOSSIL_IO_PARSER_COMBO) { - free(argument->combo_options); - } free(argument->name); - free(argument->value); + if (argument->value && argument->value != (char *)argument->combo_options) { + free(argument->value); + } argument = argument->next; } free(command->name); diff --git a/code/tests/cases/test_parser.c b/code/tests/cases/test_parser.c index a4578e2..635203d 100644 --- a/code/tests/cases/test_parser.c +++ b/code/tests/cases/test_parser.c @@ -51,6 +51,7 @@ FOSSIL_TEST_CASE(c_create_palette) { FOSSIL_TEST_ASSUME(strcmp(palette->description, "Test Description") == 0, "Palette description should be 'Test Description'"); FOSSIL_TEST_ASSUME(palette->commands == NULL, "Palette commands should be NULL"); fossil_io_parser_free(palette); + palette = NULL; } // end case FOSSIL_TEST_CASE(c_add_command) { @@ -96,6 +97,85 @@ FOSSIL_TEST_CASE(c_free_palette) { // No explicit assumptions here, just ensuring no memory leaks or crashes } // end case +FOSSIL_TEST_CASE(c_argument_types) { + fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); + fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "Test Command Description"); + + // Test BOOL argument + fossil_io_parser_argument_t *bool_arg = fossil_io_parser_add_argument(command, "bool_arg", FOSSIL_IO_PARSER_BOOL, NULL, 0); + FOSSIL_TEST_ASSUME(bool_arg != NULL, "BOOL argument should be added"); + FOSSIL_TEST_ASSUME(bool_arg->type == FOSSIL_IO_PARSER_BOOL, "BOOL argument type should be correct"); + + // Test STRING argument + fossil_io_parser_argument_t *string_arg = fossil_io_parser_add_argument(command, "string_arg", FOSSIL_IO_PARSER_STRING, NULL, 0); + FOSSIL_TEST_ASSUME(string_arg != NULL, "STRING argument should be added"); + FOSSIL_TEST_ASSUME(string_arg->type == FOSSIL_IO_PARSER_STRING, "STRING argument type should be correct"); + + // Test INT argument + fossil_io_parser_argument_t *int_arg = fossil_io_parser_add_argument(command, "int_arg", FOSSIL_IO_PARSER_INT, NULL, 0); + FOSSIL_TEST_ASSUME(int_arg != NULL, "INT argument should be added"); + FOSSIL_TEST_ASSUME(int_arg->type == FOSSIL_IO_PARSER_INT, "INT argument type should be correct"); + + // Test FLOAT argument + fossil_io_parser_argument_t *float_arg = fossil_io_parser_add_argument(command, "float_arg", FOSSIL_IO_PARSER_FLOAT, NULL, 0); + FOSSIL_TEST_ASSUME(float_arg != NULL, "FLOAT argument should be added"); + FOSSIL_TEST_ASSUME(float_arg->type == FOSSIL_IO_PARSER_FLOAT, "FLOAT argument type should be correct"); + + // Test DATE argument + fossil_io_parser_argument_t *date_arg = fossil_io_parser_add_argument(command, "date_arg", FOSSIL_IO_PARSER_DATE, NULL, 0); + FOSSIL_TEST_ASSUME(date_arg != NULL, "DATE argument should be added"); + FOSSIL_TEST_ASSUME(date_arg->type == FOSSIL_IO_PARSER_DATE, "DATE argument type should be correct"); + + // Test ARRAY argument + fossil_io_parser_argument_t *array_arg = fossil_io_parser_add_argument(command, "array_arg", FOSSIL_IO_PARSER_ARRAY, NULL, 0); + FOSSIL_TEST_ASSUME(array_arg != NULL, "ARRAY argument should be added"); + FOSSIL_TEST_ASSUME(array_arg->type == FOSSIL_IO_PARSER_ARRAY, "ARRAY argument type should be correct"); + + // Test FEATURE argument + fossil_io_parser_argument_t *feature_arg = fossil_io_parser_add_argument(command, "feature_arg", FOSSIL_IO_PARSER_FEATURE, NULL, 0); + FOSSIL_TEST_ASSUME(feature_arg != NULL, "FEATURE argument should be added"); + FOSSIL_TEST_ASSUME(feature_arg->type == FOSSIL_IO_PARSER_FEATURE, "FEATURE argument type should be correct"); + + fossil_io_parser_free(palette); +} // end case + +FOSSIL_TEST_CASE(c_null_palette) { + fossil_io_parser_palette_t *palette = NULL; + FOSSIL_TEST_ASSUME(fossil_io_parser_add_command(palette, "test_command", "Test Command Description") == NULL, "Adding command to NULL palette should return NULL"); + fossil_io_parser_parse(palette, 0, NULL); +} // end case + +FOSSIL_TEST_CASE(c_empty_command_name) { + fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); + fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "", "Empty Command Name Description"); + FOSSIL_TEST_ASSUME(command == NULL, "Command with empty name should not be added"); + fossil_io_parser_free(palette); +} // end case + +FOSSIL_TEST_CASE(c_duplicate_command_name) { + fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); + fossil_io_parser_add_command(palette, "test_command", "Test Command Description"); + fossil_io_parser_command_t *duplicate = fossil_io_parser_add_command(palette, "test_command", "Duplicate Command Description"); + FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate command name should not be allowed"); + fossil_io_parser_free(palette); +} // end case + +FOSSIL_TEST_CASE(c_null_argument_name) { + fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); + fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "Test Command Description"); + fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, NULL, FOSSIL_IO_PARSER_STRING, NULL, 0); + FOSSIL_TEST_ASSUME(argument == NULL, "Argument with NULL name should not be added"); + fossil_io_parser_free(palette); +} // end case + +FOSSIL_TEST_CASE(c_invalid_argument_type) { + fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); + fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "Test Command Description"); + fossil_io_parser_argument_t *argument = fossil_io_parser_add_argument(command, "invalid_arg", FOSSIL_IO_PARSER_INVALID, NULL, 0); + FOSSIL_TEST_ASSUME(argument == NULL, "Argument with invalid type should not be added"); + fossil_io_parser_free(palette); +} // end case + // * * * * * * * * * * * * * * * * * * * * * * * * // * Fossil Logic Test Pool // * * * * * * * * * * * * * * * * * * * * * * * * @@ -105,6 +185,12 @@ FOSSIL_TEST_GROUP(c_parser_test_cases) { FOSSIL_TEST_ADD(c_parser_suite, c_add_argument); FOSSIL_TEST_ADD(c_parser_suite, c_parse_command); FOSSIL_TEST_ADD(c_parser_suite, c_free_palette); + FOSSIL_TEST_ADD(c_parser_suite, c_argument_types); + FOSSIL_TEST_ADD(c_parser_suite, c_null_palette); + FOSSIL_TEST_ADD(c_parser_suite, c_empty_command_name); + FOSSIL_TEST_ADD(c_parser_suite, c_duplicate_command_name); + FOSSIL_TEST_ADD(c_parser_suite, c_null_argument_name); + FOSSIL_TEST_ADD(c_parser_suite, c_invalid_argument_type); FOSSIL_TEST_REGISTER(c_parser_suite); } // end of group diff --git a/code/tests/cases/test_parser.cpp b/code/tests/cases/test_parser.cpp index 91691b5..faf9d73 100644 --- a/code/tests/cases/test_parser.cpp +++ b/code/tests/cases/test_parser.cpp @@ -78,6 +78,48 @@ FOSSIL_TEST_CASE(cpp_add_argument) { fossil_io_parser_free(palette); } // end case +FOSSIL_TEST_CASE(cpp_argument_types) { + fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); + fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "Test Command Description"); + + // Test BOOL argument + fossil_io_parser_argument_t *bool_arg = fossil_io_parser_add_argument(command, "bool_arg", FOSSIL_IO_PARSER_BOOL, NULL, 0); + FOSSIL_TEST_ASSUME(bool_arg != NULL, "BOOL argument should be added"); + FOSSIL_TEST_ASSUME(bool_arg->type == FOSSIL_IO_PARSER_BOOL, "BOOL argument type should be correct"); + + // Test STRING argument + fossil_io_parser_argument_t *string_arg = fossil_io_parser_add_argument(command, "string_arg", FOSSIL_IO_PARSER_STRING, NULL, 0); + FOSSIL_TEST_ASSUME(string_arg != NULL, "STRING argument should be added"); + FOSSIL_TEST_ASSUME(string_arg->type == FOSSIL_IO_PARSER_STRING, "STRING argument type should be correct"); + + // Test INT argument + fossil_io_parser_argument_t *int_arg = fossil_io_parser_add_argument(command, "int_arg", FOSSIL_IO_PARSER_INT, NULL, 0); + FOSSIL_TEST_ASSUME(int_arg != NULL, "INT argument should be added"); + FOSSIL_TEST_ASSUME(int_arg->type == FOSSIL_IO_PARSER_INT, "INT argument type should be correct"); + + // Test FLOAT argument + fossil_io_parser_argument_t *float_arg = fossil_io_parser_add_argument(command, "float_arg", FOSSIL_IO_PARSER_FLOAT, NULL, 0); + FOSSIL_TEST_ASSUME(float_arg != NULL, "FLOAT argument should be added"); + FOSSIL_TEST_ASSUME(float_arg->type == FOSSIL_IO_PARSER_FLOAT, "FLOAT argument type should be correct"); + + // Test DATE argument + fossil_io_parser_argument_t *date_arg = fossil_io_parser_add_argument(command, "date_arg", FOSSIL_IO_PARSER_DATE, NULL, 0); + FOSSIL_TEST_ASSUME(date_arg != NULL, "DATE argument should be added"); + FOSSIL_TEST_ASSUME(date_arg->type == FOSSIL_IO_PARSER_DATE, "DATE argument type should be correct"); + + // Test ARRAY argument + fossil_io_parser_argument_t *array_arg = fossil_io_parser_add_argument(command, "array_arg", FOSSIL_IO_PARSER_ARRAY, NULL, 0); + FOSSIL_TEST_ASSUME(array_arg != NULL, "ARRAY argument should be added"); + FOSSIL_TEST_ASSUME(array_arg->type == FOSSIL_IO_PARSER_ARRAY, "ARRAY argument type should be correct"); + + // Test FEATURE argument + fossil_io_parser_argument_t *feature_arg = fossil_io_parser_add_argument(command, "feature_arg", FOSSIL_IO_PARSER_FEATURE, NULL, 0); + FOSSIL_TEST_ASSUME(feature_arg != NULL, "FEATURE argument should be added"); + FOSSIL_TEST_ASSUME(feature_arg->type == FOSSIL_IO_PARSER_FEATURE, "FEATURE argument type should be correct"); + + fossil_io_parser_free(palette); +} // end case + FOSSIL_TEST_CASE(cpp_parse_command) { fossil_io_parser_palette_t *palette = fossil_io_parser_create_palette("test_palette", "Test Description"); fossil_io_parser_command_t *command = fossil_io_parser_add_command(palette, "test_command", "Test Command Description"); @@ -165,6 +207,89 @@ FOSSIL_TEST_CASE(cpp_wrapper_free_palette) { // No explicit assumptions here, just ensuring no memory leaks or crashes } // end case +FOSSIL_TEST_CASE(cpp_wrapper_argument_types) { + fossil::io::Parser parser; + fossil_io_parser_palette_t *palette = parser.create_palette("wrapper_palette", "Wrapper Test Description"); + fossil_io_parser_command_t *command = parser.add_command(palette, "wrapper_command", "Wrapper Command Description"); + + // Test BOOL argument + fossil_io_parser_argument_t *bool_arg = parser.add_argument(command, "bool_arg", FOSSIL_IO_PARSER_BOOL, NULL, 0); + FOSSIL_TEST_ASSUME(bool_arg != NULL, "BOOL argument should be added"); + FOSSIL_TEST_ASSUME(bool_arg->type == FOSSIL_IO_PARSER_BOOL, "BOOL argument type should be correct"); + + // Test STRING argument + fossil_io_parser_argument_t *string_arg = parser.add_argument(command, "string_arg", FOSSIL_IO_PARSER_STRING, NULL, 0); + FOSSIL_TEST_ASSUME(string_arg != NULL, "STRING argument should be added"); + FOSSIL_TEST_ASSUME(string_arg->type == FOSSIL_IO_PARSER_STRING, "STRING argument type should be correct"); + + // Test INT argument + fossil_io_parser_argument_t *int_arg = parser.add_argument(command, "int_arg", FOSSIL_IO_PARSER_INT, NULL, 0); + FOSSIL_TEST_ASSUME(int_arg != NULL, "INT argument should be added"); + FOSSIL_TEST_ASSUME(int_arg->type == FOSSIL_IO_PARSER_INT, "INT argument type should be correct"); + + // Test FLOAT argument + fossil_io_parser_argument_t *float_arg = parser.add_argument(command, "float_arg", FOSSIL_IO_PARSER_FLOAT, NULL, 0); + FOSSIL_TEST_ASSUME(float_arg != NULL, "FLOAT argument should be added"); + FOSSIL_TEST_ASSUME(float_arg->type == FOSSIL_IO_PARSER_FLOAT, "FLOAT argument type should be correct"); + + // Test DATE argument + fossil_io_parser_argument_t *date_arg = parser.add_argument(command, "date_arg", FOSSIL_IO_PARSER_DATE, NULL, 0); + FOSSIL_TEST_ASSUME(date_arg != NULL, "DATE argument should be added"); + FOSSIL_TEST_ASSUME(date_arg->type == FOSSIL_IO_PARSER_DATE, "DATE argument type should be correct"); + + // Test ARRAY argument + fossil_io_parser_argument_t *array_arg = parser.add_argument(command, "array_arg", FOSSIL_IO_PARSER_ARRAY, NULL, 0); + FOSSIL_TEST_ASSUME(array_arg != NULL, "ARRAY argument should be added"); + FOSSIL_TEST_ASSUME(array_arg->type == FOSSIL_IO_PARSER_ARRAY, "ARRAY argument type should be correct"); + + // Test FEATURE argument + fossil_io_parser_argument_t *feature_arg = parser.add_argument(command, "feature_arg", FOSSIL_IO_PARSER_FEATURE, NULL, 0); + FOSSIL_TEST_ASSUME(feature_arg != NULL, "FEATURE argument should be added"); + FOSSIL_TEST_ASSUME(feature_arg->type == FOSSIL_IO_PARSER_FEATURE, "FEATURE argument type should be correct"); + parser.free(palette); +} // end case + +FOSSIL_TEST_CASE(cpp_wrapper_null_palette) { + fossil::io::Parser parser; + fossil_io_parser_palette_t *palette = NULL; + FOSSIL_TEST_ASSUME(parser.add_command(palette, "test_command", "Test Command Description") == NULL, "Adding command to NULL palette should return NULL"); + parser.parse(palette, 0, NULL); +} // end case + +FOSSIL_TEST_CASE(cpp_wrapper_empty_command_name) { + fossil::io::Parser parser; + fossil_io_parser_palette_t *palette = parser.create_palette("wrapper_palette", "Wrapper Test Description"); + fossil_io_parser_command_t *command = parser.add_command(palette, "", "Empty Command Name Description"); + FOSSIL_TEST_ASSUME(command == NULL, "Command with empty name should not be added"); + parser.free(palette); +} // end case + +FOSSIL_TEST_CASE(cpp_wrapper_duplicate_command_name) { + fossil::io::Parser parser; + fossil_io_parser_palette_t *palette = parser.create_palette("wrapper_palette", "Wrapper Test Description"); + parser.add_command(palette, "wrapper_command", "Wrapper Command Description"); + fossil_io_parser_command_t *duplicate = parser.add_command(palette, "wrapper_command", "Duplicate Command Description"); + FOSSIL_TEST_ASSUME(duplicate == NULL, "Duplicate command name should not be allowed"); + parser.free(palette); +} // end case + +FOSSIL_TEST_CASE(cpp_wrapper_null_argument_name) { + fossil::io::Parser parser; + fossil_io_parser_palette_t *palette = parser.create_palette("wrapper_palette", "Wrapper Test Description"); + fossil_io_parser_command_t *command = parser.add_command(palette, "wrapper_command", "Wrapper Command Description"); + fossil_io_parser_argument_t *argument = parser.add_argument(command, NULL, FOSSIL_IO_PARSER_STRING, NULL, 0); + FOSSIL_TEST_ASSUME(argument == NULL, "Argument with NULL name should not be added"); + parser.free(palette); +} // end case + +FOSSIL_TEST_CASE(cpp_wrapper_invalid_argument_type) { + fossil::io::Parser parser; + fossil_io_parser_palette_t *palette = parser.create_palette("wrapper_palette", "Wrapper Test Description"); + fossil_io_parser_command_t *command = parser.add_command(palette, "wrapper_command", "Wrapper Command Description"); + fossil_io_parser_argument_t *argument = parser.add_argument(command, "invalid_arg", FOSSIL_IO_PARSER_INVALID, NULL, 0); + FOSSIL_TEST_ASSUME(argument == NULL, "Argument with invalid type should not be added"); + parser.free(palette); +} // end case // * * * * * * * * * * * * * * * * * * * * * * * * // * Fossil Logic Test Pool @@ -176,11 +301,19 @@ FOSSIL_TEST_GROUP(cpp_parser_test_cases) { FOSSIL_TEST_ADD(cpp_parser_suite, cpp_add_argument); FOSSIL_TEST_ADD(cpp_parser_suite, cpp_parse_command); FOSSIL_TEST_ADD(cpp_parser_suite, cpp_free_palette); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_argument_types); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_create_palette); FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_add_command); FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_add_argument); FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_parse_command); FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_free_palette); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_argument_types); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_null_palette); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_empty_command_name); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_duplicate_command_name); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_null_argument_name); + FOSSIL_TEST_ADD(cpp_parser_suite, cpp_wrapper_invalid_argument_type); FOSSIL_TEST_REGISTER(cpp_parser_suite); } // end of group