#include "lex.h" #include "parse.h" #include "typeutils.h" #include #include typedef struct { char* key; char* val; } StrPair; DECLARE_VEC(StrPair, KeyValMap) DECLARE_MAYBE(char*, MaybeStr) void set_map_pair(KeyValMap* map, char* key, char* val) { for (int i = 0; i < map->count; i++) { char* key_i = get_from_KeyValMap(map, i)->key; if (key_i == NULL) continue; if (strcmp(key_i, key) == 0) { // TODO: maybe copy instead strcpy( map->blocks[i / map->block_size][i % map->block_size].val, val ); break; } } } MaybeStr get_map_value(KeyValMap* map, char* key) { for (int i = 0; i < map->count; i++) { char* key_i = get_from_KeyValMap(map, i)->key; if (key_i == NULL) continue; if (strcmp(key_i, key) == 0) { return (MaybeStr){ .some = true, .value = get_from_KeyValMap(map, i)->val }; } } return (MaybeStr){.some = false}; } void unset_map_key(KeyValMap* map, char* key) { for (int i = 0; i < map->count; i++) { char* key_i = get_from_KeyValMap(map, i)->key; if (key_i == NULL) continue; if (strcmp(key_i, key) == 0) { map->blocks[i / map->block_size][i % map->block_size].key = NULL; break; } } } typedef struct { KeyValMap aliases; KeyValMap shell_vars; } ShellState; char* get_var(char* varname, ShellState* shstate) { MaybeStr maybe_varval = get_map_value(&shstate->shell_vars, varname); if (maybe_varval.some == true) return maybe_varval.value; return getenv(varname); } 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}; } DECLARE_VEC(char*, StrVec) 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]); } } } StrVec expand_word(Word word, ShellState* state) { WordSplittingGerm curr_res = {.complete_strs = make_StrVec(256), .active_str = make_String(25)}; for (int i = 0; i < word.count; i++) { Chunk curr_cunk = *get_from_Word(&word, i); ExpandedChunk curr_exp = expand_chunk(curr_cunk, state); switch (curr_exp.qmode) { case UN_Q: add_expchunk(curr_exp.content, &curr_res); break; case SINGLE_Q: append_str_to_String(&curr_res.active_str, curr_exp.content); break; case DOUBLE_Q: append_str_to_String(&curr_res.active_str, curr_exp.content); } } if (curr_res.active_str.count > 0) { push_to_StrVec(&curr_res.complete_strs, inner(&curr_res.active_str)); } return curr_res.complete_strs; /* char** res_ptr = malloc(sizeof(char*) * curr_res.complete_strs.count); for (int j = 0; j < curr_res.complete_strs.count; j++) { res_ptr[j] = curr_res.complete_strs.blocks[j / curr_res.complete_strs.block_size][j % curr_res.complete_strs.block_size]; } return res_ptr; */ } char** expand_token(Token token, ShellState* shstate) { // TODO: alias expansion // TODO: make some kind of extractor for the Vec-s that returns a regular T*-type NULL-term array // TODO: we need to split strs on spaces exit(1); } void command_thing(Command command, ShellState* shtate) { char** } void run_pipeline(Pipeline pl, ShellState* shstate) { }