diff options
| author | Ákos Kőrösi <korakos99@gmail.com> | 2026-05-19 21:13:19 +0200 |
|---|---|---|
| committer | Ákos Kőrösi <korakos99@gmail.com> | 2026-05-19 21:13:19 +0200 |
| commit | 2bdbf387261285d07e4b62d1e23c9e43efb14604 (patch) | |
| tree | 92b81d300f3c17d072f2a30362dafd815e57a758 /src/expand.c | |
| parent | 6a391a1180766ac5717c40efa70d46cacca83f91 (diff) | |
restructure dir, create makefile
Diffstat (limited to 'src/expand.c')
| -rw-r--r-- | src/expand.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/expand.c b/src/expand.c new file mode 100644 index 0000000..11764f9 --- /dev/null +++ b/src/expand.c @@ -0,0 +1,104 @@ +#include "expand.h" +#include "preproc.h" +#include "utils.h" +#include <string.h> + + +typedef struct { + QuotationMode qmode; + char* content; +} ExpandedChunk; + + +ExpandedChunk expand_chunk(Chunk chunk, ShellState* shstate) { + char* content; + if (chunk.qmode == SINGLE_Q || chunk.kind == LITERAL) { + if (chunk.qmode == SINGLE_Q && chunk.kind != LITERAL) exit(69); + content = chunk.as.literal_str; + } else if (chunk.kind == VAR_EXP) { + content = get_var(chunk.as.varname, shstate); + } else if (chunk.kind == REGION_EXP) { + exit(7); // Not supported yet; arithm + } + return (ExpandedChunk){.qmode = chunk.qmode, .content = content}; +} + + +typedef struct { + StrVec complete_strs; + String active_str; +} WordSplittingGerm; + +void add_expchunk(char* next_str, WordSplittingGerm* curr_res) { + for (int pos = 0; pos < strlen(next_str); pos++) { + if (next_str[pos] == ' ') { + push_to_StrVec(&curr_res->complete_strs, inner(&curr_res->active_str)); + curr_res->active_str = make_String(256); + } else { + push_to_String(&curr_res->active_str, next_str[pos]); + } + } +} + + +void expand_word(Word word, SlotVec* target, ShellState* shstate) { + WordSplittingGerm curr_res = { + .complete_strs = make_StrVec(256), + .active_str = make_String(256) + }; + for (int i = 0; i < word.count; i++) { + Chunk chunk = **get_from_Word(&word, i); + ExpandedChunk expchunk = expand_chunk(chunk, shstate); + switch (expchunk.qmode) { + case UN_Q: + add_expchunk(expchunk.content, &curr_res); + break; + case SINGLE_Q: + append_str_to_String(&curr_res.active_str, expchunk.content); + break; + case DOUBLE_Q: + // TODO: further expansions here + append_str_to_String(&curr_res.active_str, expchunk.content); + break; + } + } + if (curr_res.active_str.count > 0) { + push_to_StrVec(&curr_res.complete_strs, inner(&curr_res.active_str)); + } + for (int j = 0; j < curr_res.complete_strs.count; j++) { + char* str = *get_from_StrVec(&curr_res.complete_strs, j); + push_to_SlotVec(target, (Slot){.kind = SLOT_STR, .as.str = str}); + } +} + +ExpandedPipelineElement expand_pipeline_element(PipelineElement elem, ShellState* shstate) { + ExpandedPipelineElement result = {.cmd_slots = make_SlotVec(256), .conn = elem.conn}; + for (int i = 0; i < elem.cmd_toks.count; i++) { + Token curr_tok = *get_from_TokenVec(&elem.cmd_toks, i); + switch (curr_tok.kind) { + case TOK_WORD: + expand_word(curr_tok.as.word, &result.cmd_slots, shstate); + break; + case TOK_SPECIAL: + push_to_SlotVec(&result.cmd_slots, (Slot){.kind = SLOT_SPEC, .as.spec = curr_tok.as.spec}); + break; + case TOK_PROCSUB_IN: + push_to_SlotVec(&result.cmd_slots, (Slot){.kind = SLOT_PROC_IN, .as.proc_reg= curr_tok.as.procsub_region}); + break; + case TOK_PROCSUB_OUT: + push_to_SlotVec(&result.cmd_slots, (Slot){.kind = SLOT_PROC_OUT, .as.proc_reg= curr_tok.as.procsub_region}); + break; + } + } + return result; +} + +ExpandedPipeline expand_pipeline(Pipeline* pl, ShellState *shstate) { + ExpandedPipeline exp_pl = make_ExpandedPipeline(256); + for (int i = 0; i < pl->count; i++) { + PipelineElement elem = *get_from_Pipeline(pl, i); + ExpandedPipelineElement exp_elem = expand_pipeline_element(elem, shstate); + push_to_ExpandedPipeline(&exp_pl, exp_elem); + } + return exp_pl; +} |
