mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2024-06-06 12:29:31 +00:00
process vector of commands all at once.
This commit is contained in:
parent
6d9e5dc78c
commit
475bd392ad
|
@ -14,9 +14,10 @@
|
||||||
nl = '\n' | '\r';
|
nl = '\n' | '\r';
|
||||||
|
|
||||||
action push_token {
|
action push_token {
|
||||||
if (!scratch.empty()) {
|
if (!scratch.empty() || quoted) {
|
||||||
tokens.emplace_back(std::move(scratch));
|
tokens.emplace_back(std::move(scratch));
|
||||||
scratch.clear();
|
scratch.clear();
|
||||||
|
quoted = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@
|
||||||
[']
|
[']
|
||||||
( (any-nl-[']) $push_back )*
|
( (any-nl-[']) $push_back )*
|
||||||
[']
|
[']
|
||||||
|
${ quoted = true; }
|
||||||
$err{
|
$err{
|
||||||
throw std::runtime_error("### MPW Shell - 's must occur in pairs.");
|
throw std::runtime_error("### MPW Shell - 's must occur in pairs.");
|
||||||
}
|
}
|
||||||
|
@ -88,6 +90,7 @@
|
||||||
(any-escape-["]) $push_back
|
(any-escape-["]) $push_back
|
||||||
)*
|
)*
|
||||||
["]
|
["]
|
||||||
|
${ quoted = true; }
|
||||||
$err{
|
$err{
|
||||||
throw std::runtime_error("### MPW Shell - \"s must occur in pairs.");
|
throw std::runtime_error("### MPW Shell - \"s must occur in pairs.");
|
||||||
}
|
}
|
||||||
|
@ -221,6 +224,8 @@ std::vector<token> tokenize(const std::string &s, bool eval)
|
||||||
{
|
{
|
||||||
std::vector<token> tokens;
|
std::vector<token> tokens;
|
||||||
std::string scratch;
|
std::string scratch;
|
||||||
|
bool quoted = false; // found a quote character ("" creates a token)
|
||||||
|
|
||||||
|
|
||||||
%%machine tokenizer;
|
%%machine tokenizer;
|
||||||
%% write data;
|
%% write data;
|
||||||
|
@ -240,7 +245,7 @@ std::vector<token> tokenize(const std::string &s, bool eval)
|
||||||
throw std::runtime_error("MPW Shell - Lexer error.");
|
throw std::runtime_error("MPW Shell - Lexer error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scratch.empty()) {
|
if (!scratch.empty() || quoted) {
|
||||||
tokens.emplace_back(std::move(scratch));
|
tokens.emplace_back(std::move(scratch));
|
||||||
scratch.clear();
|
scratch.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
#include "mapped_file.h"
|
#include "mapped_file.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
//#include <histedit.h>
|
//#include <histedit.h>
|
||||||
#include <editline/readline.h>
|
#include <editline/readline.h>
|
||||||
|
@ -29,20 +30,20 @@ void init(Environment &e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_file(phase1 &p, const std::string &file) {
|
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.begin(), mf.end(), true);
|
||||||
p.process(mf.const_begin(), mf.const_end(), true);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int read_stdin(phase1 &p) {
|
|
||||||
|
int read_fd(phase1 &p, int fd) {
|
||||||
|
|
||||||
unsigned char buffer[2048];
|
unsigned char buffer[2048];
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
size = read(STDIN_FILENO, buffer, sizeof(buffer));
|
size = read(fd, buffer, sizeof(buffer));
|
||||||
if (size == 0) break;
|
if (size == 0) break;
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
|
@ -77,7 +78,12 @@ int interactive(phase1 &p) {
|
||||||
free(cp);
|
free(cp);
|
||||||
|
|
||||||
if (s.empty()) continue;
|
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');
|
s.push_back('\n');
|
||||||
try {
|
try {
|
||||||
p.process(s);
|
p.process(s);
|
||||||
|
@ -107,23 +113,38 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
phase1 p1;
|
phase1 p1;
|
||||||
phase2 p2;
|
phase2 p2;
|
||||||
p1 >>= p2;
|
|
||||||
|
|
||||||
p2 >>= [&e](command_ptr &&ptr) {
|
|
||||||
fdmask fds;
|
|
||||||
ptr->execute(e, fds);
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
p1 >>= [&p2](std::string &&s) {
|
p1 >>= [&p2](std::string &&s) {
|
||||||
|
if (s.empty()) p2.finish();
|
||||||
fprintf(stdout, " -> %s\n", s.c_str());
|
else p2(std::move(s));
|
||||||
p2.process(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();
|
p2.finish();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
2
phase2.h
2
phase2.h
|
@ -43,7 +43,7 @@ protected:
|
||||||
class phase2 {
|
class phase2 {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::function<void(command_ptr &&)> pipe_function;
|
typedef std::function<void(command_ptr_vector &&)> pipe_function;
|
||||||
|
|
||||||
phase2();
|
phase2();
|
||||||
phase2(const phase2 &) = delete;
|
phase2(const phase2 &) = delete;
|
||||||
|
|
|
@ -202,6 +202,8 @@ void phase2::classify() {
|
||||||
|
|
||||||
void phase2::process(const std::string &line) {
|
void phase2::process(const std::string &line) {
|
||||||
|
|
||||||
|
if (line.empty()) { finish(); return; }
|
||||||
|
|
||||||
int pcount = 0; // special form parens cannot cross lines.
|
int pcount = 0; // special form parens cannot cross lines.
|
||||||
|
|
||||||
int cs;
|
int cs;
|
||||||
|
@ -238,12 +240,13 @@ void phase2::parse(int token, std::string &&s) {
|
||||||
void phase2::exec() {
|
void phase2::exec() {
|
||||||
|
|
||||||
if (pipe_to && parser) {
|
if (pipe_to && parser) {
|
||||||
|
command_ptr_vector tmp;
|
||||||
for (auto &p : parser->command_queue) {
|
for (auto &p : parser->command_queue) {
|
||||||
if (p) {
|
if (p) tmp.emplace_back(std::move(p));
|
||||||
pipe_to(std::move(p));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
parser->command_queue.clear();
|
parser->command_queue.clear();
|
||||||
|
|
||||||
|
if (!tmp.empty()) pipe_to(std::move(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user