summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--redes/exec.c147
-rw-r--r--redes/main.c23
-rw-r--r--redes/preproc.c135
-rw-r--r--src/exec.c194
-rw-r--r--src/exec.h26
-rw-r--r--src/expand.c104
-rw-r--r--src/expand.h31
-rw-r--r--src/lexparse.c (renamed from redes/lexparse.c)0
-rw-r--r--src/main.c10
-rw-r--r--src/preproc.c393
-rw-r--r--src/preproc.h116
-rw-r--r--src/stages.h (renamed from redes/stages.h)0
-rw-r--r--src/syntax.h (renamed from redes/syntax.h)0
14 files changed, 187 insertions, 997 deletions
diff --git a/Makefile b/Makefile
index b0c058a..9377222 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,3 @@
build:
- @gcc -g src/main.c src/exec.c src/expand.c src/preproc.c src/utils.c -o bin/yeesh -lreadline
-
+ @gcc -g src/main.c src/exec.c src/preproc.c src/lexparse.c src/utils.c -o bin/yeesh -lreadline
-redesbuild:
- @gcc -g redes/main.c redes/exec.c redes/preproc.c redes/lexparse.c src/utils.c -o bin/reyeesh -lreadline
diff --git a/redes/exec.c b/redes/exec.c
deleted file mode 100644
index afdf140..0000000
--- a/redes/exec.c
+++ /dev/null
@@ -1,147 +0,0 @@
-#include <stdio.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <sys/wait.h>
-
-#include "syntax.h"
-
-
-void execute_cmd(ExecutableCommand cmd, int* pgid) {
-
- pid_t pid = fork();
-
- if (pid == 0) {
-
- if (*pgid == -1) {
- setpgid(0, 0);
- } else {
- setpgid(0, *pgid);
- }
-
- dup2(cmd.stdin_fd, STDIN_FILENO);
- dup2(cmd.stdout_fd, STDOUT_FILENO);
-
- for (int i = 0; i < cmd.redirects.count; i++) {
- FdRedirect fd_rd = *get_from_FdRedirectVec(&cmd.redirects, i);
- dup2(fd_rd.to, fd_rd.redirected);
- }
-
- for (int j = 0; j < cmd.open_fds.count; j++) {
- int fd = *get_from_IntVec(&cmd.open_fds, j);
- close(fd);
- }
-
- signal(SIGINT, SIG_DFL);
- signal(SIGQUIT, SIG_DFL);
- signal(SIGTSTP, SIG_DFL);
- signal(SIGTTIN, SIG_DFL);
- signal(SIGTTOU, SIG_DFL);
-
- execvp(cmd.args[0], cmd.args);
- exit(67);
- }
-
- if (*pgid == -1) {
- setpgid(pid, pid);
- *pgid = pid;
- } else {
- setpgid(pid, *pgid);
- }
-}
-
-
-ExecutableCommand process_pl_command(PlCommand pl_cmd) {
- StrVec arg_vec = make_StrVec(256);
- for (int i = 0; i < pl_cmd.args.count; i++) {
- Arg arg = *get_from_ArgVec(&pl_cmd.args, i);
- switch (arg.kind) {
- case ARG_LIT:
- push_to_StrVec(&arg_vec, arg.as.lit_str);
- break;
- default:
- exit(67);
- }
- }
-
- FdRedirectVec fd_redirs = make_FdRedirectVec(256);
- IntVec open_fds = make_IntVec(256);
- for (int j = 0; j < pl_cmd.redirects.count; j++) {
- Redirect redir = *get_from_RedirectVec(&pl_cmd.redirects, j);
- FdRedirect fd_redir;
- int fd;
- switch (redir.kind) {
- case REDIR_READ:
- fd = open(redir.as.filename, O_RDONLY, 0644);
- push_to_IntVec(&open_fds, fd);
- fd_redir = (FdRedirect){.to = fd, .redirected = STDIN_FILENO};
- break;
- case REDIR_WRITE_APPEND:
- fd = open(redir.as.filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
- push_to_IntVec(&open_fds, fd);
- fd_redir = (FdRedirect){.to = fd, .redirected = STDOUT_FILENO};
- break;
- case REDIR_WRITE_TRUNC:
- fd = open(redir.as.filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- push_to_IntVec(&open_fds, fd);
- fd_redir = (FdRedirect){.to = fd, .redirected = STDOUT_FILENO};
- break;
- default:
- exit(67);
- }
- push_to_FdRedirectVec(&fd_redirs, fd_redir);
-}
-
- char** args = malloc(sizeof(char*) * (arg_vec.count + 1));
- for (int i = 0; i < arg_vec.count; i++) {
- args[i] = *get_from_StrVec(&arg_vec, i);
- }
- args[arg_vec.count] = NULL;
-
- return (ExecutableCommand){.args = args, .redirects = fd_redirs, .open_fds = open_fds};
-}
-
-
-void execute_command_pipeline(Pipeline pipeline) {
- int trunk_fd = STDIN_FILENO;
- int pgid = -1;
-
-
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
-
- for (int i = 0; i < pipeline.count; i++) {
- PlCommand cmd = *get_from_Pipeline(&pipeline, i);
- ExecutableCommand exec_cmd = process_pl_command(cmd);
-
- exec_cmd.stdin_fd = trunk_fd;
- if (i > 0) {
- push_to_IntVec(&exec_cmd.open_fds, trunk_fd);
- }
-
- exec_cmd.stdout_fd = STDOUT_FILENO;
-
- if (cmd.conn == CONN_PIPE) {
- int pipe_fds[2];
- pipe(pipe_fds);
- exec_cmd.stdout_fd = pipe_fds[1];
- push_to_IntVec(&exec_cmd.open_fds, pipe_fds[1]);
- trunk_fd = pipe_fds[0];
- }
-
- execute_cmd(exec_cmd, &pgid);
-
- for (int j = 0; j < exec_cmd.open_fds.count; j++) {
- int fd = *get_from_IntVec(&exec_cmd.open_fds, j);
- close(fd);
- }
- }
-
- tcsetpgrp(STDIN_FILENO, pgid);
- while (waitpid(-pgid, NULL, 0) > 0);
- tcsetpgrp(STDIN_FILENO, getpgrp());
-}
-
-void execute_pipeline_tree(PipelineTree pltree) {
- execute_command_pipeline(*pltree.root);
-}
diff --git a/redes/main.c b/redes/main.c
deleted file mode 100644
index dc451f9..0000000
--- a/redes/main.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-#include <string.h>
-
-#include "syntax.h"
-#include "stages.h"
-
-
-int main() {
- char* line;
- while (1) {
- line = readline("$ ");
- if (line[0] == '\0') continue;
- if (strcmp(line, "exit") == 0) exit(0);
- add_history(line);
- Ast ast = lex(line);
- PipelineTree pltree = process_ast(ast);
- execute_pipeline_tree(pltree);
- }
- free(line);
-}
diff --git a/redes/preproc.c b/redes/preproc.c
deleted file mode 100644
index 63e618f..0000000
--- a/redes/preproc.c
+++ /dev/null
@@ -1,135 +0,0 @@
-#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) {
- char* buf_str = inner(&buf);
- push_to_StrVec(result, buf_str);
- }
-}
-
-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;
-}
-
-
-typedef struct {
- TokenKind kind;
- union {
- char* word;
- SpecialToken spec;
- } as;
-} ExpandedToken;
-
-DECLARE_VEC(ExpandedToken, ExpandedTokenVec)
-
-Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) {
-
- ExpandedTokenVec exp_tokens = make_ExpandedTokenVec(256);
-
- for (int m = 0; m < tokens.count; m++) {
- Token tok = *get_from_TokenVec(&tokens, m);
- StrVec strs;
- switch (tok.kind) {
- case TOK_SPEC:
- push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_SPEC, .as.spec = tok.as.spec});
- break;
- case TOK_WORD:
- strs = process_word(tok.as.word);
- for (int n = 0; n < strs.count; n++) {
- push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_WORD, .as.word = *get_from_StrVec(&strs, n)});
- }
- }
- }
-
- Pipeline pl = make_Pipeline(256);
- size_t tok_pos = 0;
-
- PlCommand curr_cmd = {.args = make_ArgVec(256), .redirects = make_RedirectVec(256), .conn = CONN_EOL};
-
- PlCommand* root_pl;
- for (int i = 0; i < exp_tokens.count; i++) {
- ExpandedToken curr_tok = *get_from_ExpandedTokenVec(&exp_tokens, i);
- ExpandedToken next_tok;
- Redirect rd;
- switch (curr_tok.kind) {
- case TOK_WORD:
- push_to_ArgVec(&curr_cmd.args, (Arg){.kind = ARG_LIT, .as.lit_str = curr_tok.as.word});
- break;
- case TOK_SPEC:
- switch (curr_tok.as.spec.kind) {
- case SPEC_OP:
- switch (curr_tok.as.spec.as.op) {
- case OP_PIPE:
- curr_cmd.conn = CONN_PIPE;
- push_to_Pipeline(&pl, curr_cmd);
- curr_cmd = (PlCommand){.args = make_ArgVec(256), .redirects = make_RedirectVec(256), .conn = CONN_EOL};
- break;
- case OP_EOL:
- push_to_Pipeline(&pl, curr_cmd);
- break;
- case OP_REDIR_R:
- next_tok = *get_from_ExpandedTokenVec(&exp_tokens, ++i);
- assert(next_tok.kind == TOK_WORD);
- rd = (Redirect){.kind = REDIR_READ, .as.filename = next_tok.as.word};
- push_to_RedirectVec(&curr_cmd.redirects, rd);
- break;
- case OP_REDIR_W_APPEND:
- next_tok = *get_from_ExpandedTokenVec(&exp_tokens, ++i);
- assert(next_tok.kind == TOK_WORD);
- rd = (Redirect){.kind = REDIR_WRITE_APPEND, .as.filename = next_tok.as.word};
- push_to_RedirectVec(&curr_cmd.redirects, rd);
- break;
- case OP_REDIR_W_TRUNC:
- next_tok = *get_from_ExpandedTokenVec(&exp_tokens, ++i);
- assert(next_tok.kind == TOK_WORD);
- rd = (Redirect){.kind = REDIR_WRITE_TRUNC, .as.filename = next_tok.as.word};
- push_to_RedirectVec(&curr_cmd.redirects, rd);
- break;
- default:
- exit(63);
- }
- break;
- default:
- exit(62);
- }
- }
- }
- 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};
-}
diff --git a/src/exec.c b/src/exec.c
index fccda7a..afdf140 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -1,38 +1,35 @@
#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/wait.h>
-#include "utils.h"
-#include "exec.h"
-#include "preproc.h"
-#include "expand.h"
+#include "syntax.h"
-void execute_command(Command cmd, int* pgid) {
+void execute_cmd(ExecutableCommand cmd, int* pgid) {
pid_t pid = fork();
-
+
if (pid == 0) {
- if (*pgid == -1) {
+
+ if (*pgid == -1) {
setpgid(0, 0);
} else {
setpgid(0, *pgid);
}
-
+
dup2(cmd.stdin_fd, STDIN_FILENO);
dup2(cmd.stdout_fd, STDOUT_FILENO);
- for (int j = 0; j < cmd.redirs.count; j++) {
- FdRedirect fd_rd = *get_from_FdRedirectVec(&cmd.redirs, j);
- dup2(fd_rd.new_fd, fd_rd.old_fd);
+ for (int i = 0; i < cmd.redirects.count; i++) {
+ FdRedirect fd_rd = *get_from_FdRedirectVec(&cmd.redirects, i);
+ dup2(fd_rd.to, fd_rd.redirected);
}
- for (int i = 0; i < cmd.child_close_fds.count; i++) {
- close(*get_from_IntVec(&cmd.child_close_fds, i));
+ for (int j = 0; j < cmd.open_fds.count; j++) {
+ int fd = *get_from_IntVec(&cmd.open_fds, j);
+ close(fd);
}
signal(SIGINT, SIG_DFL);
@@ -53,102 +50,90 @@ void execute_command(Command cmd, int* pgid) {
}
}
-Command make_command(ExpandedPipelineElement elem) {
- Command cmd = {
- .child_close_fds = make_IntVec(64),
- .parent_close_fds = make_IntVec(64),
- .redirs = make_FdRedirectVec(32),
- .term = elem.conn,
- };
- StrVec arg_strs = make_StrVec(256);
- for (int i = 0; i < elem.cmd_slots.count; i++) {
- Slot curr_slot = *get_from_SlotVec(&elem.cmd_slots, i);
- Slot next_slot;
+
+ExecutableCommand process_pl_command(PlCommand pl_cmd) {
+ StrVec arg_vec = make_StrVec(256);
+ for (int i = 0; i < pl_cmd.args.count; i++) {
+ Arg arg = *get_from_ArgVec(&pl_cmd.args, i);
+ switch (arg.kind) {
+ case ARG_LIT:
+ push_to_StrVec(&arg_vec, arg.as.lit_str);
+ break;
+ default:
+ exit(67);
+ }
+ }
+
+ FdRedirectVec fd_redirs = make_FdRedirectVec(256);
+ IntVec open_fds = make_IntVec(256);
+ for (int j = 0; j < pl_cmd.redirects.count; j++) {
+ Redirect redir = *get_from_RedirectVec(&pl_cmd.redirects, j);
+ FdRedirect fd_redir;
int fd;
- FdRedirect redir;
- switch (curr_slot.kind) {
- case SLOT_STR:
- push_to_StrVec(&arg_strs, curr_slot.as.str);
+ switch (redir.kind) {
+ case REDIR_READ:
+ fd = open(redir.as.filename, O_RDONLY, 0644);
+ push_to_IntVec(&open_fds, fd);
+ fd_redir = (FdRedirect){.to = fd, .redirected = STDIN_FILENO};
+ break;
+ case REDIR_WRITE_APPEND:
+ fd = open(redir.as.filename, O_WRONLY | O_CREAT | O_APPEND, 0644);
+ push_to_IntVec(&open_fds, fd);
+ fd_redir = (FdRedirect){.to = fd, .redirected = STDOUT_FILENO};
break;
- case SLOT_SPEC:
- switch (curr_slot.as.spec) {
- case READ_REDIR:
- i++;
- next_slot = *get_from_SlotVec(&elem.cmd_slots, i);
- if (next_slot.kind != SLOT_STR) exit(6);
- fd = open(next_slot.as.str, O_RDONLY, 0644);
- redir = (FdRedirect){.old_fd = STDIN_FILENO, .new_fd = fd};
- push_to_FdRedirectVec(&cmd.redirs, redir);
- push_to_IntVec(&cmd.parent_close_fds, fd);
- push_to_IntVec(&cmd.child_close_fds, fd);
- break;
- case WRITE_REDIR_TRUNC:
- i++;
- next_slot = *get_from_SlotVec(&elem.cmd_slots, i);
- if (next_slot.kind != SLOT_STR) exit(6);
- fd = open(next_slot.as.str, O_WRONLY | O_CREAT | O_TRUNC , 0644);
- redir = (FdRedirect){.old_fd = STDOUT_FILENO, .new_fd = fd};
- push_to_FdRedirectVec(&cmd.redirs, redir);
- push_to_IntVec(&cmd.parent_close_fds, fd);
- push_to_IntVec(&cmd.child_close_fds, fd);
- break;
- case WRITE_REDIR_APPEND:
- i++;
- next_slot = *get_from_SlotVec(&elem.cmd_slots, i);
- if (next_slot.kind != SLOT_STR) exit(6);
- fd = open(next_slot.as.str, O_WRONLY | O_CREAT | O_APPEND, 0644);
- redir = (FdRedirect){.old_fd = STDOUT_FILENO, .new_fd = fd};
- push_to_FdRedirectVec(&cmd.redirs, redir);
- push_to_IntVec(&cmd.parent_close_fds, fd);
- push_to_IntVec(&cmd.child_close_fds, fd);
- break;
- default:
- exit(7);
- }
+ case REDIR_WRITE_TRUNC:
+ fd = open(redir.as.filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ push_to_IntVec(&open_fds, fd);
+ fd_redir = (FdRedirect){.to = fd, .redirected = STDOUT_FILENO};
break;
default:
exit(67);
- // TODO: other slot kinds
}
- }
- cmd.args = malloc(sizeof(char*) * arg_strs.count);
- for (int j = 0; j < arg_strs.count; j++) {
- cmd.args[j] = *get_from_StrVec(&arg_strs, j);
- }
- return cmd;
+ push_to_FdRedirectVec(&fd_redirs, fd_redir);
}
+ char** args = malloc(sizeof(char*) * (arg_vec.count + 1));
+ for (int i = 0; i < arg_vec.count; i++) {
+ args[i] = *get_from_StrVec(&arg_vec, i);
+ }
+ args[arg_vec.count] = NULL;
+
+ return (ExecutableCommand){.args = args, .redirects = fd_redirs, .open_fds = open_fds};
+}
-void run_cmds(CommandVec cmds) {
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
+void execute_command_pipeline(Pipeline pipeline) {
int trunk_fd = STDIN_FILENO;
int pgid = -1;
- for (int i = 0; i < cmds.count; i++) {
- Command cmd = *get_from_CommandVec(&cmds, i);
- cmd.stdin_fd = trunk_fd;
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+
+ for (int i = 0; i < pipeline.count; i++) {
+ PlCommand cmd = *get_from_Pipeline(&pipeline, i);
+ ExecutableCommand exec_cmd = process_pl_command(cmd);
+
+ exec_cmd.stdin_fd = trunk_fd;
if (i > 0) {
- push_to_IntVec(&cmd.child_close_fds, trunk_fd);
- push_to_IntVec(&cmd.parent_close_fds, trunk_fd);
+ push_to_IntVec(&exec_cmd.open_fds, trunk_fd);
}
- cmd.stdout_fd = STDOUT_FILENO;
- if (cmd.term == CONN_PIPE) {
+ exec_cmd.stdout_fd = STDOUT_FILENO;
+
+ if (cmd.conn == CONN_PIPE) {
int pipe_fds[2];
pipe(pipe_fds);
- cmd.stdout_fd = pipe_fds[1];
- push_to_IntVec(&cmd.child_close_fds, pipe_fds[1]);
- push_to_IntVec(&cmd.parent_close_fds, pipe_fds[1]);
+ exec_cmd.stdout_fd = pipe_fds[1];
+ push_to_IntVec(&exec_cmd.open_fds, pipe_fds[1]);
trunk_fd = pipe_fds[0];
}
- execute_command(cmd, &pgid);
-
- for (int j = 0; j < cmd.parent_close_fds.count; j++) {
- close(*get_from_IntVec(&cmd.parent_close_fds, j));
+ execute_cmd(exec_cmd, &pgid);
+
+ for (int j = 0; j < exec_cmd.open_fds.count; j++) {
+ int fd = *get_from_IntVec(&exec_cmd.open_fds, j);
+ close(fd);
}
}
@@ -157,33 +142,6 @@ void run_cmds(CommandVec cmds) {
tcsetpgrp(STDIN_FILENO, getpgrp());
}
-
-CommandVec make_cmd_vec_pl(ExpandedPipeline pl) {
- CommandVec cmds = make_CommandVec(256);
- for (int i = 0; i < pl.count; i++) {
- ExpandedPipelineElement elem = *get_from_ExpandedPipeline(&pl, i);
- Command cmd = make_command(elem);
- push_to_CommandVec(&cmds, cmd);
- }
- return cmds;
-}
-
-
-void process_input_line(char* line, ShellState* shstate) {
- PreprocArena arena = {
- .tokens = make_TokenVec(256),
- .chunks = make_ChunkVec(256),
- .regions = make_RegionVec(256),
- };
- TokenPtrVec line_tok_ptrs = lex(line, &arena);
- Token* line_toks = malloc(sizeof(Token) * line_tok_ptrs.count);
- for (int i = 0; i < line_tok_ptrs.count; i++) {
- line_toks[i] = **get_from_TokenPtrVec(&line_tok_ptrs, i);
- }
- Pipeline pl = parse_tokstream(line_toks);
- ExpandedPipeline exp_pl = expand_pipeline(&pl, shstate);
- CommandVec cmds = make_cmd_vec_pl(exp_pl);
- run_cmds(cmds);
- free(line_toks);
+void execute_pipeline_tree(PipelineTree pltree) {
+ execute_command_pipeline(*pltree.root);
}
-
diff --git a/src/exec.h b/src/exec.h
deleted file mode 100644
index 9ee8164..0000000
--- a/src/exec.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include "utils.h"
-#include "preproc.h"
-
-
-typedef struct {
- int old_fd;
- int new_fd;
-} FdRedirect;
-
-DECLARE_VEC(FdRedirect, FdRedirectVec)
-
-typedef struct {
- char** args;
- FdRedirectVec redirs;
- int stdin_fd;
- int stdout_fd;
- IntVec child_close_fds;
- IntVec parent_close_fds;
- Connector term;
-} Command;
-
-DECLARE_VEC(Command, CommandVec)
-
-void process_input_line(char* line, ShellState* shstate);
diff --git a/src/expand.c b/src/expand.c
deleted file mode 100644
index 11764f9..0000000
--- a/src/expand.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#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;
-}
diff --git a/src/expand.h b/src/expand.h
deleted file mode 100644
index b353f39..0000000
--- a/src/expand.h
+++ /dev/null
@@ -1,31 +0,0 @@
-# pragma once
-
-#include "preproc.h"
-#include "utils.h"
-
-typedef enum {
- SLOT_STR,
- SLOT_SPEC,
- SLOT_PROC_IN,
- SLOT_PROC_OUT,
-} SlotKind;
-
-typedef struct {
- SlotKind kind;
- union {
- char* str;
- SpecialToken spec;
- Region* proc_reg;
- } as;
-} Slot;
-
-DECLARE_VEC(Slot, SlotVec)
-
-typedef struct {
- SlotVec cmd_slots;
- Connector conn;
-} ExpandedPipelineElement;
-
-DECLARE_VEC(ExpandedPipelineElement, ExpandedPipeline)
-
-ExpandedPipeline expand_pipeline(Pipeline* pl, ShellState* shstate);
diff --git a/redes/lexparse.c b/src/lexparse.c
index 3a55b33..3a55b33 100644
--- a/redes/lexparse.c
+++ b/src/lexparse.c
diff --git a/src/main.c b/src/main.c
index 35c2bff..dc451f9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -4,20 +4,20 @@
#include <readline/history.h>
#include <string.h>
-#include "exec.h"
+#include "syntax.h"
+#include "stages.h"
int main() {
char* line;
- ShellState shstate = {.shell_vars = make_KeyValMap(1), .aliases = make_KeyValMap(1)};
while (1) {
line = readline("$ ");
if (line[0] == '\0') continue;
if (strcmp(line, "exit") == 0) exit(0);
add_history(line);
- process_input_line(line, &shstate);
+ Ast ast = lex(line);
+ PipelineTree pltree = process_ast(ast);
+ execute_pipeline_tree(pltree);
}
free(line);
}
-
-
diff --git a/src/preproc.c b/src/preproc.c
index 4cd1c5b..63e618f 100644
--- a/src/preproc.c
+++ b/src/preproc.c
@@ -1,318 +1,135 @@
-#include <ctype.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
+#include <assert.h>
#include <stdio.h>
+#include "syntax.h"
-#include "preproc.h"
-#include "utils.h"
-
-
-// Lexing
-
-typedef struct {
- char* str;
- size_t pos;
-} RawLine;
-
-
-String collect_identifier(RawLine* line) {
- String id_buf = make_String(256);
- while (line->str[line->pos] == '_' || isalnum(line->str[line->pos])) {
- push_to_String(&id_buf, line->str[line->pos++]);
- }
- return id_buf;
-}
-
-
-
-TokenPtrVec lex_level(RawLine* line, char until, PreprocArena* arena);
-
-
-void expect_char(RawLine* line, char expected) {
- if (line->str[line->pos] != expected) {
- exit(45); // TODO: nicer handling
- }
- line->pos++;
-}
-
-
-/*
-MaybeChunk lex_expansion_chunk(RawLine* line, RegionVec* reg_arena, QuotationMode qmode) {
- line->pos++; // Consume $
- if (line->str[line->pos] == '(') {
- line->pos++;
- if (line->str[line->pos] == '(') {
- exit(1);
- // TODO: this (and potentially the other parsers must be custom, we need to recognize arithm-internal parens from the terminating `))` )
-
-
- TokenVec inner_toks = lex_level(line, ')', reg_arena);
- expect_char(line, ')');
- expect_char(line, ')');
- Region* reg_ptr = push_to_RegionVec(
- reg_arena,
- (Region){.mode = ARITHM, .tokens = inner_toks}
- );
- return (MaybeChunk){
- .some = true,
- .value = (Chunk){
- .qmode = qmode,
- .kind = REGION_EXP,
- .as.reg_ptr = reg_ptr
- },
- };
- } else {
- TokenVec inner_toks = lex_level(line, ')', reg_arena);
- expect_char(line, ')');
- Region* reg_ptr = push_to_RegionVec(
- reg_arena,
- (Region){.mode = CMDS, .tokens = inner_toks}
- );
- return (MaybeChunk) {
- .some = true,
- .value = (Chunk){
- .qmode = qmode,
- .kind = REGION_EXP,
- .as.reg_ptr = reg_ptr,
- }
- };
- }
- } else {
- String id_name = collect_identifier(line);
- if (id_name.count > 0) {
- return (MaybeChunk){
- .some = true,
- .value = (Chunk){
- .qmode = qmode,
- .kind = VAR_EXP,
- .as.varname = inner(&id_name),
- }
- };
- }
- }
- return (MaybeChunk){.some = false};
-}
-*/
-
-
-void lex_double_quoted_section(RawLine* line, Word* coll, PreprocArena* arena) {
- line->pos++;
- String accum = make_String(256);
- while (line->str[line->pos] != '\"') {
- if (line->str[line->pos] == '\0') exit(43);
-
- MaybeChunk exp_chunk = {.some = false};
-
- if (line->str[line->pos] == '$') {
- exit(1);
- /*
- exp_chunk = lex_expansion_chunk(line, reg_arena, DOUBLE_Q);
- if (!exp_chunk.some) {
- push_to_String(&accum, '$');
- }
- */
+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(&accum, line->str[line->pos++]);
- }
- // TODO: other special cases beyond $
-
- if (exp_chunk.some) {
- if (accum.count > 0) {
- Chunk accum_chunk = {.qmode = DOUBLE_Q, .kind = LITERAL, .as.literal_str = inner(&accum)};
- Chunk* accum_ptr = push_to_ChunkVec(&arena->chunks, accum_chunk);
- push_to_Word(coll, accum_ptr);
- accum = make_String(256);
- }
- Chunk* exp_ptr = push_to_ChunkVec(&arena->chunks, exp_chunk.value);
- push_to_Word(coll, exp_ptr);
- exp_chunk.some = false;
+ push_to_String(&buf, str[pos]);
}
}
- line->pos++;
- if (accum.count > 0) {
- Chunk accum_chunk = {.qmode = DOUBLE_Q, .kind = LITERAL, .as.literal_str = inner(&accum)};
- Chunk* accum_ptr = push_to_ChunkVec(&arena->chunks, accum_chunk);
- push_to_Word(coll, accum_ptr);
- accum = make_String(256);
- }
-}
-
-Chunk next_word_unquoted(RawLine* line, RegionVec* reg_arena) {
- String buf = make_String(256);
- for (char c; (c=line->str[line->pos], c != '$' && c != '\0' && c != ' '); line->pos++) {
- push_to_String(&buf, c);
+ if (buf.count > 0) {
+ char* buf_str = inner(&buf);
+ push_to_StrVec(result, buf_str);
}
- return (Chunk){.qmode = UN_Q, .kind = LITERAL, .as.literal_str = inner(&buf)};
}
-
-Chunk collect_single_quoted_section(RawLine* line) {
- line->pos++; // Consume quote mark
- String chunk_str = make_String(256);
- while (line->str[line->pos] != '\'') {
- if (line->str[line->pos] == '\0') exit(44);
- push_to_String(&chunk_str, line->str[line->pos++]);
+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;
+ }
}
- line->pos++; // Consume closing quote
- return (Chunk){
- .qmode = SINGLE_Q,
- .kind = LITERAL,
- .as.literal_str = inner(&chunk_str),
- };
+ return result;
}
typedef struct {
- Word word_germ;
- String unq_liter_germ;
-} LexState;
-
-
-void close_word_and_lit_germs(LexState* state, TokenPtrVec* toks, PreprocArena* arena) {
- if (state->unq_liter_germ.count > 0) {
- Chunk chu = {
- .qmode = UN_Q,
- .kind = LITERAL,
- .as.literal_str = inner(&state->unq_liter_germ)
- };
- Chunk* chu_ptr = push_to_ChunkVec(&arena->chunks, chu);
- push_to_Word(&state->word_germ, chu_ptr);
- state->unq_liter_germ = make_String(256);
- }
- if (state->word_germ.count > 0) {
- Token tok = {.kind = TOK_WORD, .as.word = state->word_germ};
- Token* tok_ptr = push_to_TokenVec(&arena->tokens, tok);
- push_to_TokenPtrVec(toks, tok_ptr);
- state->word_germ = make_Word(256);
- }
-}
+ TokenKind kind;
+ union {
+ char* word;
+ SpecialToken spec;
+ } as;
+} ExpandedToken;
-TokenPtrVec lex_level(RawLine* line, char until, PreprocArena* arena) {
+DECLARE_VEC(ExpandedToken, ExpandedTokenVec)
- TokenPtrVec line_toks = make_TokenPtrVec(256);
- LexState state = {
- .word_germ = make_Word(256),
- .unq_liter_germ = make_String(256)
- };
+Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool) {
- while (line->str[line->pos] != until) {
+ ExpandedTokenVec exp_tokens = make_ExpandedTokenVec(256);
- if (line->str[line->pos] == ' ') {
- close_word_and_lit_germs(&state, &line_toks, arena);
- while (line->str[line->pos] == ' ') line->pos++;
- continue;
+ for (int m = 0; m < tokens.count; m++) {
+ Token tok = *get_from_TokenVec(&tokens, m);
+ StrVec strs;
+ switch (tok.kind) {
+ case TOK_SPEC:
+ push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_SPEC, .as.spec = tok.as.spec});
+ break;
+ case TOK_WORD:
+ strs = process_word(tok.as.word);
+ for (int n = 0; n < strs.count; n++) {
+ push_to_ExpandedTokenVec(&exp_tokens, (ExpandedToken){.kind = TOK_WORD, .as.word = *get_from_StrVec(&strs, n)});
+ }
}
+ }
- Token* tok_ptr;
+ Pipeline pl = make_Pipeline(256);
+ size_t tok_pos = 0;
- switch (line->str[line->pos]) {
- case '\'':
- push_to_Word(&state.word_germ, push_to_ChunkVec(&arena->chunks, collect_single_quoted_section(line)));
- break;
- case '\"':
- lex_double_quoted_section(line, &state.word_germ, arena);
- break;
- case '|':
- line->pos++;
- close_word_and_lit_germs(&state, &line_toks, arena);
- tok_ptr = push_to_TokenVec(&arena->tokens, (Token){.kind = TOK_SPECIAL, .as.spec = PIPE});
- push_to_TokenPtrVec(&line_toks, tok_ptr);
- break;
- case '$':
- exit(1);
- /*
- line->pos++;
- MaybeChunk mchunk = lex_expansion_chunk(line, reg_arena, UN_Q);
- if (mchunk.some) {
- push_to_Word(&state.word_germ, mchunk.value);
- } else {
- push_to_String(&state.unq_liter_germ, '$');
- }
- */
- break;
- case '>':
- close_word_and_lit_germs(&state, &line_toks, arena);
- line->pos++;
+ PlCommand curr_cmd = {.args = make_ArgVec(256), .redirects = make_RedirectVec(256), .conn = CONN_EOL};
- switch (line->str[line->pos]) {
- case '(':
- line->pos++;
- TokenPtrVec sub_regtoks = lex_level(line, ')', arena);
- line->pos++;
- Region subreg = {.mode = CMDS, .tokens = sub_regtoks};
- Region* subreg_ptr = push_to_RegionVec(&arena->regions, subreg);
- Token tok = {.kind = TOK_PROCSUB_OUT, .as.procsub_region = subreg_ptr};
- tok_ptr = push_to_TokenVec(&arena->tokens, tok);
- push_to_TokenPtrVec(&line_toks, tok_ptr);
- break;
- case '>':
- line->pos++;
- tok_ptr = push_to_TokenVec(&arena->tokens, (Token){.kind = TOK_SPECIAL, .as.spec = WRITE_REDIR_APPEND});
- push_to_TokenPtrVec(&line_toks, tok_ptr);
+ PlCommand* root_pl;
+ for (int i = 0; i < exp_tokens.count; i++) {
+ ExpandedToken curr_tok = *get_from_ExpandedTokenVec(&exp_tokens, i);
+ ExpandedToken next_tok;
+ Redirect rd;
+ switch (curr_tok.kind) {
+ case TOK_WORD:
+ push_to_ArgVec(&curr_cmd.args, (Arg){.kind = ARG_LIT, .as.lit_str = curr_tok.as.word});
+ break;
+ case TOK_SPEC:
+ switch (curr_tok.as.spec.kind) {
+ case SPEC_OP:
+ switch (curr_tok.as.spec.as.op) {
+ case OP_PIPE:
+ curr_cmd.conn = CONN_PIPE;
+ push_to_Pipeline(&pl, curr_cmd);
+ curr_cmd = (PlCommand){.args = make_ArgVec(256), .redirects = make_RedirectVec(256), .conn = CONN_EOL};
+ break;
+ case OP_EOL:
+ push_to_Pipeline(&pl, curr_cmd);
+ break;
+ case OP_REDIR_R:
+ next_tok = *get_from_ExpandedTokenVec(&exp_tokens, ++i);
+ assert(next_tok.kind == TOK_WORD);
+ rd = (Redirect){.kind = REDIR_READ, .as.filename = next_tok.as.word};
+ push_to_RedirectVec(&curr_cmd.redirects, rd);
+ break;
+ case OP_REDIR_W_APPEND:
+ next_tok = *get_from_ExpandedTokenVec(&exp_tokens, ++i);
+ assert(next_tok.kind == TOK_WORD);
+ rd = (Redirect){.kind = REDIR_WRITE_APPEND, .as.filename = next_tok.as.word};
+ push_to_RedirectVec(&curr_cmd.redirects, rd);
+ break;
+ case OP_REDIR_W_TRUNC:
+ next_tok = *get_from_ExpandedTokenVec(&exp_tokens, ++i);
+ assert(next_tok.kind == TOK_WORD);
+ rd = (Redirect){.kind = REDIR_WRITE_TRUNC, .as.filename = next_tok.as.word};
+ push_to_RedirectVec(&curr_cmd.redirects, rd);
+ break;
+ default:
+ exit(63);
+ }
break;
default:
- tok_ptr = push_to_TokenVec(&arena->tokens, (Token){.kind = TOK_SPECIAL, .as.spec = WRITE_REDIR_TRUNC});
- push_to_TokenPtrVec(&line_toks, tok_ptr);
+ exit(62);
}
- break;
- case '<':
- close_word_and_lit_germs(&state, &line_toks, arena);
- line->pos++;
- if (line->str[line->pos] == '(') {
- line->pos++;
- TokenPtrVec sub_regtoks = lex_level(line, ')', arena);
- line->pos++;
- Region subreg = {.mode = CMDS, .tokens = sub_regtoks};
- Region* reg_ptr = push_to_RegionVec(&arena->regions, subreg);
- Token reg_tok = {.kind = TOK_PROCSUB_IN, .as.procsub_region = reg_ptr};
- Token* reg_tok_ptr = push_to_TokenVec(&arena->tokens, reg_tok);
- push_to_TokenPtrVec(&line_toks, reg_tok_ptr);
- } else {
- Token* redir_ptr = push_to_TokenVec(&arena->tokens, (Token){.kind = TOK_SPECIAL, .as.spec = READ_REDIR});
- push_to_TokenPtrVec(&line_toks, redir_ptr);
- }
- break;
- default:
- push_to_String(&state.unq_liter_germ, line->str[line->pos++]);
}
- }
- // TODO: handle until char _and_ EOL
- close_word_and_lit_germs(&state, &line_toks, arena);
- return line_toks;
-}
-
-
-TokenPtrVec lex(char* input, PreprocArena* arena) {
- RawLine line = {.str = input, .pos = 0};
- TokenPtrVec toks = lex_level(&line, '\0', arena);
- Token* eol_ptr = push_to_TokenVec(&arena->tokens, (Token){.kind = TOK_SPECIAL, .as.spec = EOL});
- push_to_TokenPtrVec(&toks, eol_ptr);
- return toks;
+ }
+ return push_to_PipelineVec(pl_pool, pl);
}
-
-
-// Parsing
-
-Pipeline parse_tokstream(Token* toks) {
- size_t tok_pos = 0;
- Pipeline result = make_Pipeline(256);
- TokenVec tok_buf = make_TokenVec(256);
- while (true) {
- Token curr_tok = toks[tok_pos++];
- if (curr_tok.kind == TOK_SPECIAL && curr_tok.as.spec == PIPE) {
- push_to_Pipeline(&result, (PipelineElement){.cmd_toks = tok_buf, .conn = CONN_PIPE});
- tok_buf = make_TokenVec(256);
- } else if (curr_tok.kind == TOK_SPECIAL && curr_tok.as.spec == EOL) {
- push_to_Pipeline(&result, (PipelineElement){.cmd_toks = tok_buf, .conn = CONN_EOL});
- break;
- } else {
- push_to_TokenVec(&tok_buf, curr_tok);
- }
- }
- return result;
+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};
}
diff --git a/src/preproc.h b/src/preproc.h
deleted file mode 100644
index 7907f9d..0000000
--- a/src/preproc.h
+++ /dev/null
@@ -1,116 +0,0 @@
-#pragma once
-
-#include "utils.h"
-
-typedef struct Region Region;
-
-
-// Lexing stage
-typedef enum {
- UN_Q,
- SINGLE_Q,
- DOUBLE_Q,
-} QuotationMode;
-
-typedef enum {
- LITERAL,
- REGION_EXP,
- VAR_EXP, // TODO: Later include other exps
-} ChunkKind;
-
-typedef struct {
- ChunkKind kind;
- QuotationMode qmode;
- union {
- char* literal_str;
- Region* reg_ptr;
- char* varname;
- } as;
-} Chunk;
-DECLARE_MAYBE(Chunk, MaybeChunk);
-DECLARE_VEC(Chunk*, Word)
-
-typedef enum {
- TOK_WORD,
- TOK_SPECIAL,
- TOK_PROCSUB_IN,
- TOK_PROCSUB_OUT,
-} TokenKind;
-
-typedef enum {
- PIPE,
- WRITE_REDIR_TRUNC,
- WRITE_REDIR_APPEND,
- READ_REDIR,
- EOL,
-} SpecialToken;
-DECLARE_MAYBE(SpecialToken, MaybeSpecialToken)
-
-typedef struct {
- TokenKind kind;
-
- union {
- Word word;
- SpecialToken spec;
- Region* procsub_region;
- } as;
-} Token;
-
-
-DECLARE_VEC(Token*, TokenPtrVec)
-
-
-typedef enum {
- CMDS,
- ARITHM,
-} RegionMode;
-
-struct Region {
- RegionMode mode;
- TokenPtrVec tokens;
-};
-DECLARE_VEC(Region, RegionVec)
-
-
-
-DECLARE_VEC(Chunk, ChunkVec)
-DECLARE_VEC(Token, TokenVec)
-
-
-
-// Lexing
-
-typedef struct {
- RegionVec regions;
- TokenVec tokens;
- ChunkVec chunks;
-} PreprocArena;
-
-
-TokenPtrVec lex(char* input, PreprocArena* arena);
-
-
-// Parsing
-
-typedef enum {
- CONN_PIPE,
- CONN_EOL,
- // TODO: add the |& thingy
-} Connector;
-
-DECLARE_MAYBE(Connector, MaybeConnector)
-
-typedef struct {
- TokenVec cmd_toks;
- Connector conn;
-} PipelineElement;
-
-DECLARE_VEC(PipelineElement, Pipeline)
-
-Pipeline parse_tokstream(Token* tokstream);
-
-
-
-
-
-
diff --git a/redes/stages.h b/src/stages.h
index 4faaf14..4faaf14 100644
--- a/redes/stages.h
+++ b/src/stages.h
diff --git a/redes/syntax.h b/src/syntax.h
index 0cdb76c..0cdb76c 100644
--- a/redes/syntax.h
+++ b/src/syntax.h