summaryrefslogtreecommitdiff
path: root/redes/preproc.c
blob: 33a00e4a79053dc19baa8c2cc0a1e34f63934646 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <assert.h>
#include <stdio.h>
#include "syntax.h"

void split_str_on_space(char* str, StrVec* result) {
    String buf = make_String(256);
    for (int pos = 0; str[pos] != '\0'; pos++) {
        if (str[pos] == ' ') {
            push_to_StrVec(result, inner(&buf));
            buf = make_String(256);
        } else {
            push_to_String(&buf, str[pos]);
        }
    }

    if (buf.count > 0) {
        push_to_StrVec(result, inner(&buf));
    }
}

StrVec process_word(Word word) {
    StrVec result = make_StrVec(256);
    for (int i = 0; i < word.count; i++) {
        Chunk chunk = *get_from_Word(&word, i);
        switch (chunk.qmode) {
            case SINGLE_Q:
                push_to_StrVec(&result, chunk.as.lit_str);
                break;
            case DOUBLE_Q:
                // TODO
                exit(67);
                break;
            case UN_Q:
                // TODO: this only does literals, implement the rest
                split_str_on_space(chunk.as.lit_str, &result);
                break;
        }
    }
    return result;
}

Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) {
    Pipeline pl = make_Pipeline(256);
    size_t tok_pos = 0;
    while (tok_pos < tokens.count) {
        PlCommand pl_cmd = {
            .args = make_ArgVec(256),
            .redirects = make_RedirectVec(256),
            .conn = CONN_EOL,
        };
        Token curr_tok;
        for (;
            (
                curr_tok = *get_from_TokenVec(&tokens, tok_pos),
                !(curr_tok.kind == TOK_SPEC && (curr_tok.as.spec == SPEC_PIPE || curr_tok.as.spec == SPEC_EOL))
            );
            tok_pos++
        ) {
            StrVec exp_word;
            switch (curr_tok.kind) {
                case TOK_WORD:
                    exp_word = process_word(curr_tok.as.word);
                    for (int j = 0; j < exp_word.count; j++) {
                        char* arg_str = *get_from_StrVec(&exp_word, j); 
                        push_to_ArgVec(&pl_cmd.args, (Arg){.kind = ARG_LIT, .as.lit_str = arg_str});
                    }
                    break;
                default:
                    exit(68);   // TODO: the other kinds
            }
        }
        Token delim_tok = *get_from_TokenVec(&tokens, tok_pos++);
        assert(delim_tok.kind == TOK_SPEC);
        switch (delim_tok.as.spec) {
            case SPEC_PIPE:
                pl_cmd.conn = CONN_PIPE;
                break;
            case SPEC_EOL:
                pl_cmd.conn = CONN_EOL;
                break;
            default:
                exit(69);
        }
        push_to_Pipeline(&pl, pl_cmd);
    }
    return push_to_PipelineVec(pl_pool, pl); 
}


PipelineTree process_ast(Ast ast) {
    PipelineVec pls = make_PipelineVec(256);
    TokenVec root_toks = *ast.root;
    Pipeline* root_pl = process_token_sequence(root_toks, &pls);
    return (PipelineTree){.pl_pool = pls, root_pl};
}