From 4c80a78661bdd2efe2f0a07b496f2a6cc6005a06 Mon Sep 17 00:00:00 2001 From: Trent Huber Date: Tue, 1 Jul 2025 01:12:24 -0400 Subject: [PATCH] File redirection tokenization --- src/input.c | 3 ++- src/lex.c | 70 +++++++++++++++++++++++++++++++++++++++++++++-------- src/lex.h | 39 ++++++++++++++++++++++++----- src/main.c | 1 + 4 files changed, 96 insertions(+), 17 deletions(-) diff --git a/src/input.c b/src/input.c index 96b0f79..29dc7b1 100644 --- a/src/input.c +++ b/src/input.c @@ -120,10 +120,11 @@ reset: fpurge(stdout); push(&history, start); + *buffer = ';'; *end = ';'; *++end = '\0'; signal(SIGCHLD, SIG_DFL); - return start; + return buffer; } diff --git a/src/lex.c b/src/lex.c index 2843d65..642e2c8 100644 --- a/src/lex.c +++ b/src/lex.c @@ -1,15 +1,39 @@ #include #include #include +#include +#include // DEBUG #include "history.h" #include "lex.h" -static char *tokens[BUFLEN + 1]; -static struct cmd cmds[1 + (BUFLEN + 1) / 2 + 1] = {{.type = SEMI}}; +static char *tokens[1 + BUFLEN + 1]; +static struct cmd cmds[1 + (BUFLEN + 1) / 2 + 1] = {{.args = tokens, .f = cmds->freds}}; + +void printfreds(struct cmd *c) { + for (; c->f->mode != END; ++c->f) { + printf("%d", c->f->newfd); + switch (c->f->mode) { + case READ: + fputs("<", stdout); + break; + case WRITE: + fputs(">", stdout); + break; + case READWRITE: + fputs("<>", stdout); + break; + case APPEND: + fputs(">>", stdout); + break; + default:; + } + puts(c->f->old.name); + } +} struct cmd *lex(char *b) { - char **t; + char **t, *end; struct cmd *c; if (!b) return NULL; @@ -17,34 +41,60 @@ struct cmd *lex(char *b) { c = cmds; while (*b) switch (*b) { default: - if (!*(b - 1)) { - if (c->type) { - (++c)->args = t; - c->type = NONE; - } + if (!*(b - 1)) { // Start of a token + if (!c->args) c->args = t; // Start of a command *t++ = b; } ++b; break; case '<': case '>': + if (*(b - 1)) { + if ((c->f->newfd = strtol(*--t, &end, 10)) < 0 || end != b) { + warnx("Invalid file redirection operator"); + c->args = NULL; + return c - 1; + } + if (c->args == t) c->args = NULL; + } else c->f->newfd = *b == '>'; + c->f->mode = *b++; + if (*b == '>') { + ++b; + ++c->f->mode; + } + c->f++->old.name = b; + if (*b == '&') ++b; break; case '&': case '|': if (*b == *(b + 1)) *b = '\0'; case ';': - if (c->type == NONE) { + if (c->args) { *t++ = NULL; if (!*b) { ++b; ++c->type; } c->type += *b; + *(c->f) = (struct fred){0}; + c->f = c->freds; + + (++c)->args = NULL; } + c->f = c->freds; case ' ': *b++ = '\0'; } - *++c = (struct cmd){0}; + switch (c->type) { + case AND: + case PIPE: + case OR: + warnx("Command left open-ended"); + c->args = NULL; + return c - 1; + default: + *++c = (struct cmd){0}; + } return cmds; } diff --git a/src/lex.h b/src/lex.h index b865490..f3b26fb 100644 --- a/src/lex.h +++ b/src/lex.h @@ -1,5 +1,4 @@ enum terminator { - NONE, SEMI = ';', BG = '&', AND, @@ -7,21 +6,49 @@ enum terminator { OR, }; +enum mode { + END, + READ = '<', + READWRITE, + WRITE = '>', + APPEND, +}; + +enum type { + FD, + NAME, +}; + +// if (cmd->f->type == NAME) cmd->f->old.fd = open(cmd->f->old.name, mode); +// dup2(cmd->f->newfd, cmd->f->old.fd); +// if (cmd->f->type == NAME) close(cmd->f->old.fd); +// +// // vs. +// +// if (*cmd->f->oldfd == '&') fd = open(++cmd->f->oldfd, mode); +// dup2(cmd->f->newfd, cmd-> + struct fred { - int newfd, mode; - char *oldfd; + int newfd; + enum mode mode; + enum type type; + union { + int fd; + char *name; + } old; }; -/* a>&b -> dup2(b, a); reopen(a, "w"); - * a<&b -> dup2(b, a); reopen(a, "r"); +/* a>&b -> dup2(b, a); reopen(a, "w"); | (1)>&3 -> dup2(3, 1); + * a<&b -> dup2(b, a); reopen(a, "r"); | (0)<&3 -> dup2(3, 0); * x >a >b >c ... */ struct cmd { char **args; enum terminator type; + struct fred *f, freds[(BUFLEN - 1) / 3 + 1]; int pipe[2]; - struct fred freds[(BUFLEN - 1) / 3 + 1]; }; +void printfreds(struct cmd *c); struct cmd *lex(char *b); diff --git a/src/main.c b/src/main.c index 2b00fe5..d090458 100644 --- a/src/main.c +++ b/src/main.c @@ -44,6 +44,7 @@ int main(void) { while ((cmd = lex(input()))) { while (prev = cmd++, cmd->args) { + printfreds(cmd); ispipe = cmd->type == PIPE || prev->type == PIPE; ispipestart = ispipe && prev->type != PIPE; ispipeend = ispipe && cmd->type != PIPE; -- 2.51.0