#include #include #include #include #include #define DECLARE_VEC(T, Name) \ typedef struct { \ T* items; \ size_t count; \ size_t cap; \ size_t incr_step; \ } Name; \ static inline Name make_##Name(size_t step) { \ return (Name) { \ .items = malloc(step* sizeof(T)), \ .count = 0, \ .cap = step, \ .incr_step = step, \ }; \ } \ static inline void push_to_##Name(Name* vec, T item) { \ if (vec->count == vec->cap) { \ vec->cap += vec->incr_step; \ vec->items = realloc( \ vec->items, \ vec->cap * sizeof(T) \ ); \ } \ vec->items[vec->count++] = item; \ } \ DECLARE_VEC(char, String); void append_str_to_String(String* target, char* src_str) { size_t required_size = ((target->count + strlen(src_str)) / target->incr_step + 1) * target->incr_step; if (required_size > target->cap) { target->cap = required_size; target->items = realloc(target->items, required_size * sizeof(char)); } memcpy(target->items + target->count, src_str, strlen(src_str)); target->count += strlen(src_str); } #define DECLARE_MAYBE(T) \ typedef struct { \ bool some; \ T value; \ } Maybe##T; \ typedef enum { UN_Q, SINGLE_Q, DOUBLE_Q, } QuotationMode; typedef struct Region Region; typedef enum { LITERAL, CMD_SUB, ARITHM, PARAM, } ChunkKind; typedef struct { ChunkKind kind; QuotationMode mode; union { char* lit_str; Region* sub_cmd_region; Region* arithm_expr_region; Region* param_region; } as; } Chunk; DECLARE_VEC(Chunk, ChunkVec) typedef enum { TOK_WORD, TOK_SPECIAL, } TokenKind; typedef enum { PIPE, WRITE_REDIR_TRUNC, WRITE_REDIR_APPEND, READ_REDIR, EOL, } SpecialToken; typedef struct { TokenKind kind; union { ChunkVec word; SpecialToken spec; } as; } Token; DECLARE_VEC(Token, TokenVec) DECLARE_MAYBE(SpecialToken) struct Region { QuotationMode mode; TokenVec tokens; }; DECLARE_MAYBE(Chunk); MaybeChunk unquoted_next_chunk(char* input, size_t* pos) { String chunk; char curr_c; for (;(curr_c = input[*pos], curr_c != '$' && curr_c != '\'' && curr_c != '\"' && curr_c != '\0'); pos++) { exit(1); } exit(1); } TokenVec lex_region(char* input, size_t* pos, char until) { TokenVec tokens = make_TokenVec(256); while (input[*pos] != until) { while (input[*pos] == ' ') (*pos)++; } return tokens; } TokenVec lex(char* input) { size_t pos = 0; return lex_region(input, &pos, '\0'); }