summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÁkos Kőrösi <korakos99@gmail.com>2026-05-22 14:09:14 +0200
committerÁkos Kőrösi <korakos99@gmail.com>2026-05-22 14:09:14 +0200
commit7a106ea8332ed6d95504fd3181f7b5f81a6c3072 (patch)
treefcc7eccd435a42f062b87f6cd549658023b9437b
parent6d36e6517d5fdf02a583fa276d009f462da3ed84 (diff)
start work on cmdsub
-rw-r--r--src/exec.c6
-rw-r--r--src/lexparse.c32
-rw-r--r--src/main.c9
-rw-r--r--src/preproc.c36
-rw-r--r--src/stages.h6
-rw-r--r--src/syntax.h2
6 files changed, 70 insertions, 21 deletions
diff --git a/src/exec.c b/src/exec.c
index 86175a9..fb579ad 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -36,7 +36,7 @@ void source_script(char* fname, ShellState* shstate) {
while (getline(&line, &len, fp) != -1) {
line[strcspn(line, "\r\n")] = '\0';
- execute_line(line, shstate);
+ execute_string_line(line, shstate);
}
free(line);
fclose(fp);
@@ -265,9 +265,9 @@ void execute_command_pipeline(Pipeline pipeline, int stdin_fd, int stdout_fd, bo
}
}
-void execute_pipeline_tree(PipelineTree pltree, ShellState* shstate) {
+void execute_pipeline_tree(Pipeline root_pl, ShellState* shstate, int stdin_fd, int stdout_fd) {
int pgid = -1;
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
- execute_command_pipeline(*pltree.root, STDIN_FILENO, STDOUT_FILENO, true, &pgid, shstate);
+ execute_command_pipeline(root_pl, stdin_fd, stdout_fd, true, &pgid, shstate);
}
diff --git a/src/lexparse.c b/src/lexparse.c
index eae5c16..2fcd909 100644
--- a/src/lexparse.c
+++ b/src/lexparse.c
@@ -16,6 +16,9 @@ typedef struct {
DECLARE_MAYBE(Token, MaybeToken)
+TokenVec* lex_level(char* line, size_t* pos, char until, TokenVecVec* tok_seq_pool);
+
+
MaybeToken consolidate_buffer(LexingBuffer* buf) {
if (buf->lit_germ.count > 0) {
push_to_Word(&buf->word_germ, (Chunk){
@@ -40,11 +43,26 @@ MaybeToken consolidate_buffer(LexingBuffer* buf) {
}
-static MaybeChunk handle_dollar_expansion(char* line, size_t* pos, QuotationMode qmode) {
+static MaybeChunk handle_dollar_expansion(char* line, size_t* pos, QuotationMode qmode, TokenVecVec* tok_seq_pool) {
(*pos)++;
if (line[*pos] == '(') {
- // TODO
- exit(66);
+ (*pos)++;
+ if (line[*pos] == '(') {
+ // TODO: arithm parsing
+ exit(66);
+ } else {
+ TokenVec* sub_region = lex_level(line, pos, ')', tok_seq_pool);
+ (*pos)++; // consume paren
+ return (MaybeChunk){
+ .some = true,
+ .value = (Chunk){
+ .qmode = qmode,
+ .kind = CHUNK_CMDSUB,
+ .as.cmdsub_toks = sub_region,
+ }
+ };
+ }
+
} else if (line[*pos] == '_' || isalnum(line[*pos])){
String buf = make_String(256);
while (line[*pos] == '_' || isalnum(line[*pos])) {
@@ -96,7 +114,7 @@ static Chunk collect_single_q_section(char* line, size_t* pos) {
};
}
-static void collect_double_q_section(char* line, Word* result_buf, size_t* pos) {
+static void collect_double_q_section(char* line, Word* result_buf, size_t* pos, TokenVecVec* tok_seq_pool) {
// TODO: add the extra double-q expansions
(*pos)++;
String lit_buf = make_String(256);
@@ -104,7 +122,7 @@ static void collect_double_q_section(char* line, Word* result_buf, size_t* pos)
while (line[*pos] != '\"' && line[*pos] != '\0') {
// TODO: handle escapes
if (line[*pos] == '$') {
- MaybeChunk m_dollar = handle_dollar_expansion(line, pos, DOUBLE_Q);
+ MaybeChunk m_dollar = handle_dollar_expansion(line, pos, DOUBLE_Q, tok_seq_pool);
if (m_dollar.some) {
if (lit_buf.count>0) {
push_to_Word(result_buf, (Chunk){.qmode = DOUBLE_Q, .kind = CHUNK_LIT, .as.lit_str = inner(&lit_buf)});
@@ -211,9 +229,9 @@ TokenVec* lex_level(char* line, size_t* pos, char until, TokenVecVec* tok_seq_po
Chunk chunk = collect_single_q_section(line, pos);
push_to_Word(&buf.word_germ, chunk);
} else if (line[*pos] == '\"') {
- collect_double_q_section(line, &buf.word_germ,pos);
+ collect_double_q_section(line, &buf.word_germ,pos, tok_seq_pool);
} else if (line[*pos] == '$') {
- MaybeChunk dollar_chunk = handle_dollar_expansion(line, pos, UN_Q);
+ MaybeChunk dollar_chunk = handle_dollar_expansion(line, pos, UN_Q, tok_seq_pool);
if (dollar_chunk.some) {
push_to_Word(&buf.word_germ, dollar_chunk.value);
} else {
diff --git a/src/main.c b/src/main.c
index 9e30c27..f93d32a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,4 +1,5 @@
#include <stdlib.h>
+#include <unistd.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
@@ -10,10 +11,10 @@
#include "utils.h"
-void execute_line(char *line, ShellState *shstate) {
+void execute_string_line(char *line, ShellState *shstate) {
Ast ast = lex(line);
- PipelineTree pltree = process_ast(ast, shstate);
- execute_pipeline_tree(pltree, shstate);
+ PipelineTree pltree = process_ast(*ast.root, shstate);
+ execute_pipeline_tree(*pltree.root, shstate, STDIN_FILENO, STDOUT_FILENO);
}
@@ -25,7 +26,7 @@ int main() {
line = readline("$ ");
if (line[0] == '\0') continue;
add_history(line);
- execute_line(line, &shstate);
+ execute_string_line(line, &shstate);
}
free(line);
}
diff --git a/src/preproc.c b/src/preproc.c
index 8865968..9c26c5f 100644
--- a/src/preproc.c
+++ b/src/preproc.c
@@ -1,7 +1,11 @@
#include <assert.h>
#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
#include "syntax.h"
#include "utils.h"
+#include "stages.h"
typedef struct {
@@ -35,6 +39,28 @@ void split_str_on_space(char* str, StrVec* result) {
}
+char* get_cmdsub_output(TokenVec sub_region, ShellState* shstate) {
+ int pipe_fds[2];
+ pipe(pipe_fds);
+
+ PipelineTree sub_tree = process_ast(sub_region, shstate);
+ // TODO: tree cleanup
+
+ execute_pipeline_tree(*sub_tree.root, shstate, STDIN_FILENO, pipe_fds[1]);
+
+ String output_buf = make_String(256);
+
+ char str_buf[256];
+ ssize_t len;
+ while ((len = read(pipe_fds[0], str_buf, sizeof(str_buf))) > 0) {
+ append_str_to_String(&output_buf, str_buf);
+ }
+ close(pipe_fds[0]);
+ close(pipe_fds[1]);
+ return inner(&output_buf);
+}
+
+
void process_chunk(Chunk chunk, SplitBuilder* builder, ShellState* shstate) {
assert(!(chunk.qmode == SINGLE_Q && chunk.kind != CHUNK_LIT));
@@ -46,6 +72,9 @@ void process_chunk(Chunk chunk, SplitBuilder* builder, ShellState* shstate) {
case CHUNK_VAR:
chunk_str = get_var(chunk.as.varname, shstate);
break;
+ case CHUNK_CMDSUB:
+ chunk_str = get_cmdsub_output(*(TokenVec*)chunk.as.cmdsub_toks, shstate);
+ break;
default:
exit(77);
}
@@ -146,7 +175,7 @@ Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool, ShellSta
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};
+ rd = (Redirect){.kind = REDIR_WRITE_TRUNC, .as.filename = next_tok.as.word};
push_to_RedirectVec(&curr_cmd.redirects, rd);
break;
default:
@@ -168,8 +197,9 @@ Pipeline* process_token_sequence(TokenVec tokens, PipelineVec* pl_pool, ShellSta
}
-PipelineTree process_ast(Ast ast, ShellState* shstate) {
+PipelineTree process_ast(TokenVec root, ShellState* shstate) {
PipelineVec pls = make_PipelineVec(256);
- Pipeline* root_pl = process_token_sequence(*ast.root, &pls, shstate);
+ Pipeline* root_pl = process_token_sequence(root, &pls, shstate);
return (PipelineTree){.pl_pool = pls, root_pl};
+ // TODO: ast cleanup
}
diff --git a/src/stages.h b/src/stages.h
index e731533..6bcdd51 100644
--- a/src/stages.h
+++ b/src/stages.h
@@ -4,7 +4,7 @@
#include "utils.h"
Ast lex(char* input);
-PipelineTree process_ast(Ast ast, ShellState* shstate);
-void execute_pipeline_tree(PipelineTree pltree, ShellState* shstate);
+PipelineTree process_ast(TokenVec root, ShellState* shstate);
+void execute_pipeline_tree(Pipeline root_pl, ShellState* shstate, int stdin_fd, int stdout_fd);
void source_script(char* fname, ShellState* shstate);
-void execute_line(char* line, ShellState* shstate);
+void execute_string_line(char* line, ShellState* shstate);
diff --git a/src/syntax.h b/src/syntax.h
index 9b34818..80ab067 100644
--- a/src/syntax.h
+++ b/src/syntax.h
@@ -61,7 +61,7 @@ typedef struct {
char* lit_str;
char* varname;
ArithmAst arithm_expr;
- // TODO: CHUNK_CMDSUB
+ void* cmdsub_toks; // NOTE: TokenVec
} as;
} Chunk;