#include "shell/task.h" #include #include struct task_case_item { struct task *body; struct mrsh_array *patterns; // struct mrsh_word * size_t index; struct task *word; }; struct task_case_clause { struct task task; struct { struct mrsh_word *word; } ast; struct { struct task *word; } tasks; char *word; struct task_case_item *selected; struct mrsh_array cases; // struct task_case_item * size_t index; }; static void task_case_clause_destroy(struct task *task) { struct task_case_clause *tcc = (struct task_case_clause *)task; for (size_t i = 0; i < tcc->cases.len; ++i) { struct task_case_item *tci = tcc->cases.data[i]; task_destroy(tci->body); free(tci); } mrsh_array_finish(&tcc->cases); task_destroy(tcc->tasks.word); mrsh_word_destroy(tcc->ast.word); free(tcc->word); free(tcc); } static int task_case_clause_poll(struct task *task, struct context *ctx) { struct task_case_clause *tcc = (struct task_case_clause *)task; if (tcc->tasks.word) { int word_status = task_poll(tcc->tasks.word, ctx); if (word_status < 0) { return word_status; } tcc->word = mrsh_word_str(tcc->ast.word); task_destroy(tcc->tasks.word); tcc->tasks.word = NULL; } while (!tcc->selected && tcc->index < tcc->cases.len) { struct task_case_item *tci = (struct task_case_item *)tcc->cases.data[tcc->index]; if (tci->word) { int word_status = task_poll(tci->word, ctx); if (word_status < 0) { return word_status; } struct mrsh_word_string *word = (struct mrsh_word_string *) tci->patterns->data[tci->index - 1]; task_destroy(tci->word); tci->word = NULL; if (fnmatch(word->str, tcc->word, 0) == 0) { tcc->selected = tci; break; } if (tci->index == tci->patterns->len) { ++tcc->index; } } else { struct mrsh_word **word_ptr = (struct mrsh_word **)&tci->patterns->data[tci->index++]; tci->word = task_word_create(word_ptr, TILDE_EXPANSION_NAME); } } if (tcc->selected) { return task_poll(tcc->selected->body, ctx); } return 0; } static const struct task_interface task_case_clause_impl = { .destroy = task_case_clause_destroy, .poll = task_case_clause_poll, }; struct task *task_case_clause_create( const struct mrsh_word *word, const struct mrsh_array *cases) { struct task_case_clause *task = calloc(1, sizeof(struct task_case_clause)); task_init(&task->task, &task_case_clause_impl); if (!mrsh_array_reserve(&task->cases, cases->len)) { free(task); return NULL; } for (size_t i = 0; i < cases->len; ++i) { struct mrsh_case_item *mci = cases->data[i]; struct task_case_item *tci = calloc(1, sizeof(struct task_case_item)); mrsh_array_add(&task->cases, tci); tci->patterns = &mci->patterns; tci->body = task_for_command_list_array(&mci->body); } task->ast.word = mrsh_word_copy(word); task->tasks.word = task_word_create(&task->ast.word, TILDE_EXPANSION_NAME); return (struct task *)task; }