From 475bd392ad1c952f2c593c931a568168ed48ec0b Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Tue, 2 Feb 2016 16:20:32 -0500 Subject: [PATCH] process vector of commands all at once. --- mpw-shell-token.rl | 9 +++++-- mpw-shell.cpp | 59 +++++++++++++++++++++++++++++++--------------- phase2.h | 2 +- phase2.rl | 9 ++++--- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/mpw-shell-token.rl b/mpw-shell-token.rl index 4fa5706..089eb1f 100644 --- a/mpw-shell-token.rl +++ b/mpw-shell-token.rl @@ -14,9 +14,10 @@ nl = '\n' | '\r'; action push_token { - if (!scratch.empty()) { + if (!scratch.empty() || quoted) { tokens.emplace_back(std::move(scratch)); scratch.clear(); + quoted = false; } } @@ -61,6 +62,7 @@ ['] ( (any-nl-[']) $push_back )* ['] + ${ quoted = true; } $err{ throw std::runtime_error("### MPW Shell - 's must occur in pairs."); } @@ -88,6 +90,7 @@ (any-escape-["]) $push_back )* ["] + ${ quoted = true; } $err{ throw std::runtime_error("### MPW Shell - \"s must occur in pairs."); } @@ -221,6 +224,8 @@ std::vector tokenize(const std::string &s, bool eval) { std::vector tokens; std::string scratch; + bool quoted = false; // found a quote character ("" creates a token) + %%machine tokenizer; %% write data; @@ -240,7 +245,7 @@ std::vector tokenize(const std::string &s, bool eval) throw std::runtime_error("MPW Shell - Lexer error."); } - if (!scratch.empty()) { + if (!scratch.empty() || quoted) { tokens.emplace_back(std::move(scratch)); scratch.clear(); } diff --git a/mpw-shell.cpp b/mpw-shell.cpp index 6cbd98b..65c98ff 100644 --- a/mpw-shell.cpp +++ b/mpw-shell.cpp @@ -17,6 +17,7 @@ #include "command.h" #include "mapped_file.h" +#include "error.h" //#include #include @@ -29,20 +30,20 @@ void init(Environment &e) { } int read_file(phase1 &p, const std::string &file) { - mapped_file mf; + const mapped_file mf(file, mapped_file::readonly); - mf.open(file, mapped_file::readonly); - p.process(mf.const_begin(), mf.const_end(), true); + p.process(mf.begin(), mf.end(), true); return 0; } -int read_stdin(phase1 &p) { + +int read_fd(phase1 &p, int fd) { unsigned char buffer[2048]; ssize_t size; for (;;) { - size = read(STDIN_FILENO, buffer, sizeof(buffer)); + size = read(fd, buffer, sizeof(buffer)); if (size == 0) break; if (size < 0) { if (errno == EINTR) continue; @@ -77,7 +78,12 @@ int interactive(phase1 &p) { free(cp); if (s.empty()) continue; - add_history(s.c_str()); + + // don't add if same as previous entry. + HIST_ENTRY *he = current_history(); + if (he == nullptr || s != he->line) + add_history(s.c_str()); + s.push_back('\n'); try { p.process(s); @@ -107,23 +113,38 @@ int main(int argc, char **argv) { phase1 p1; phase2 p2; - p1 >>= p2; - p2 >>= [&e](command_ptr &&ptr) { - fdmask fds; - ptr->execute(e, fds); - }; - /* p1 >>= [&p2](std::string &&s) { - - fprintf(stdout, " -> %s\n", s.c_str()); - p2.process(s); + if (s.empty()) p2.finish(); + else p2(std::move(s)); }; - */ - read_file(p1, "/Users/kelvin/mpw/Startup"); - p2.finish(); - interactive(p1); + p2 >>= [&e](command_ptr_vector &&v) { + + for (auto iter = v.begin(); iter != v.end(); ++iter) { + auto &ptr = *iter; + fdmask fds; + try { + ptr->execute(e, fds); + } catch (execution_of_input_terminated &ex) { + if (!(ptr->terminal() && ++iter == v.end())) { + fprintf(stderr, "%s\n", ex.what()); + } + return; + } + } + }; + + fprintf(stdout, "MPW Shell 0.0\n"); + e.startup(true); + read_file(p1, "/Users/kelvin/mpw/Startup"); + //p2.finish(); + e.startup(false); + + if (isatty(STDIN_FILENO)) + interactive(p1); + else + read_fd(p1, STDIN_FILENO); p2.finish(); return 0; diff --git a/phase2.h b/phase2.h index 24de6c3..e33f18e 100644 --- a/phase2.h +++ b/phase2.h @@ -43,7 +43,7 @@ protected: class phase2 { public: - typedef std::function pipe_function; + typedef std::function pipe_function; phase2(); phase2(const phase2 &) = delete; diff --git a/phase2.rl b/phase2.rl index 2c8fc89..0767fcb 100644 --- a/phase2.rl +++ b/phase2.rl @@ -202,6 +202,8 @@ void phase2::classify() { void phase2::process(const std::string &line) { + if (line.empty()) { finish(); return; } + int pcount = 0; // special form parens cannot cross lines. int cs; @@ -238,12 +240,13 @@ void phase2::parse(int token, std::string &&s) { void phase2::exec() { if (pipe_to && parser) { + command_ptr_vector tmp; for (auto &p : parser->command_queue) { - if (p) { - pipe_to(std::move(p)); - } + if (p) tmp.emplace_back(std::move(p)); } parser->command_queue.clear(); + + if (!tmp.empty()) pipe_to(std::move(tmp)); } }