#define _POSIX_C_SOURCE 200809L #include "./args.h" #include #include #include #include #include "../lists/lists.h" #include "../string_utils/string_utils.h" #include "../vars/vars.h" static void strlen_acc(void *acc, void *data) { size_t *len = (size_t *)acc; char *str = (char *)data; *len += strlen(str); } static char *concat_list_str(struct list *list) { char *res = NULL; size_t total_len = list_length(list) + 1; // + spaces + null terminator list_fold(list, &total_len, strlen_acc); res = malloc(total_len); if (res != NULL) { res[0] = 0; for (struct list *it = list; it != NULL; it = it->next) { strcat(res, (char *)it->data); if (it->next != NULL) strcat(res, " "); } res[total_len - 1] = 0; } return res; } static void args_in_var(struct hash_map *vars, struct list *args_list) { int arg_index = 1; char index_str[11]; for (struct list *it = args_list; it != NULL; it = it->next) { int_to_str(arg_index++, index_str); set_var_copy(vars, index_str, (char *)it->data); } char *concated_args = concat_list_str(args_list); set_var_copy(vars, "*", concated_args); char *key = strdup("@"); set_var(vars, key, concated_args, NULL); // key and concated_args consumed by hash_map int_to_str(arg_index - 1, index_str); set_var_copy(vars, "#", index_str); } int args_handler(int argc, char **argv, struct args_options *options, struct hash_map *vars) { options->type = INPUT_UNDEFINED; options->input_source = NULL; options->pretty_print = false; options->verbose = false; struct list *args_list = NULL; set_var_copy(vars, "0", argv[0]); for (int i = 1; i < argc; i++) { if (strcmp(argv[i], "--pretty-print") == 0) { options->pretty_print = true; } else if (strcmp(argv[i], "--verbose") == 0) { options->verbose = true; } else if (strcmp(argv[i], "-c") == 0) { if (options->type != INPUT_UNDEFINED) { fprintf(stderr, "Multiple input sources specified: %s\n", argv[i + 1]); return 1; } else if (i + 1 >= argc) { fprintf(stderr, "No command provided after -c\n"); return 1; } options->type = INPUT_CMD; options->input_source = argv[i + 1]; i++; } else if (argv[i][0] == '-') { fprintf(stderr, "Unknown option: %s\n", argv[i]); return 1; } else if (options->type == INPUT_UNDEFINED) { options->type = INPUT_FILE; options->input_source = argv[i]; } else { // All remaining arguments are treated as additional arguments args_list = list_append(args_list, argv[i]); continue; } } args_in_var(vars, args_list); list_destroy(&args_list); if (options->type == INPUT_UNDEFINED) options->type = INPUT_STDIN; return 0; } void args_print(struct args_options *options) { printf("Input type: %s\n", options->type == INPUT_CMD ? "COMMAND" : options->type == INPUT_FILE ? "FILE" : options->type == INPUT_STDIN ? "STDIN" : "UNDEFINED"); printf("Input source: %s\n", options->input_source ? options->input_source : "NULL"); printf("Pretty print: %s\n", options->pretty_print ? "true" : "false"); printf("Verbose: %s\n", options->verbose ? "true" : "false"); } void print_usage(FILE *std, const char *program_name) { fprintf(std, "Usage: %s [OPTIONS] [SCRIPT] [ARGUMENTS...]\n", program_name); fprintf(std, "Options:\n"); fprintf(std, " -c [SCRIPT] Execute the given command string.\n"); fprintf(std, " --pretty-print Enable pretty printing of outputs.\n"); fprintf(std, " --verbose Enable verbose mode.\n"); fprintf(std, "If no SCRIPT is provided, input is read from standard input.\n"); }