2021-03-30 23:10:58 +00:00
|
|
|
#ifdef _MSC_VER
|
2021-03-31 20:42:41 +00:00
|
|
|
/* avoid silly complaints about fopen */
|
|
|
|
# define _CRT_SECURE_NO_WARNINGS 1
|
|
|
|
/* work around clang bug with std::function (needed by linenoise) */
|
|
|
|
# if defined(__clang__) && !defined(_HAS_STATIC_RTTI)
|
|
|
|
# define _HAS_STATIC_RTTI 0
|
|
|
|
# endif
|
2021-03-30 23:10:58 +00:00
|
|
|
#endif
|
|
|
|
|
2016-09-05 19:50:24 +00:00
|
|
|
#include <signal.h>
|
|
|
|
|
2021-03-20 07:22:15 +00:00
|
|
|
#include <cmath>
|
2021-03-30 23:10:58 +00:00
|
|
|
#include <cctype>
|
2021-03-20 07:22:15 +00:00
|
|
|
#include <cstring>
|
|
|
|
#include <cstdio>
|
2017-01-30 18:38:11 +00:00
|
|
|
#include <optional>
|
2021-03-20 04:09:49 +00:00
|
|
|
#include <memory>
|
2021-03-20 06:24:25 +00:00
|
|
|
#include <iterator>
|
2021-04-12 17:53:24 +00:00
|
|
|
#include <string>
|
2017-01-30 18:38:11 +00:00
|
|
|
|
2016-09-07 20:57:28 +00:00
|
|
|
#include <cubescript/cubescript.hh>
|
2016-09-01 16:42:28 +00:00
|
|
|
|
2021-03-23 22:32:25 +00:00
|
|
|
namespace cs = cubescript;
|
2016-09-01 16:42:28 +00:00
|
|
|
|
2021-03-20 01:26:37 +00:00
|
|
|
std::string_view version = "CubeScript 0.0.1";
|
2016-09-01 16:42:28 +00:00
|
|
|
|
|
|
|
/* util */
|
|
|
|
|
2021-03-20 07:22:15 +00:00
|
|
|
#if defined(_WIN32)
|
2016-09-01 16:42:28 +00:00
|
|
|
#include <io.h>
|
|
|
|
static bool stdin_is_tty() {
|
|
|
|
return _isatty(_fileno(stdin));
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#include <unistd.h>
|
|
|
|
static bool stdin_is_tty() {
|
|
|
|
return isatty(0);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* line editing support */
|
|
|
|
|
2021-03-20 01:26:37 +00:00
|
|
|
inline std::string_view get_complete_cmd(std::string_view buf) {
|
|
|
|
std::string_view not_allowed = "\"/;()[] \t\r\n\0";
|
|
|
|
auto found = buf.find_first_of(not_allowed);
|
|
|
|
while (found != buf.npos) {
|
|
|
|
buf = buf.substr(found + 1, buf.size() - found - 1);
|
|
|
|
found = buf.find_first_of(not_allowed);
|
2016-09-02 16:20:53 +00:00
|
|
|
}
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2021-03-20 01:26:37 +00:00
|
|
|
inline std::string_view get_arg_type(char arg) {
|
2016-09-02 16:20:53 +00:00
|
|
|
switch (arg) {
|
|
|
|
case 'i':
|
|
|
|
return "int";
|
|
|
|
case 'b':
|
|
|
|
return "int_min";
|
|
|
|
case 'f':
|
|
|
|
return "float";
|
|
|
|
case 'F':
|
|
|
|
return "float_prev";
|
|
|
|
case 't':
|
|
|
|
return "any";
|
|
|
|
case 'E':
|
|
|
|
return "cond";
|
|
|
|
case 'N':
|
|
|
|
return "numargs";
|
|
|
|
case 's':
|
|
|
|
return "str";
|
|
|
|
case 'e':
|
|
|
|
return "block";
|
|
|
|
case 'r':
|
|
|
|
return "ident";
|
|
|
|
case '$':
|
|
|
|
return "self";
|
|
|
|
}
|
|
|
|
return "illegal";
|
|
|
|
}
|
|
|
|
|
2021-03-20 01:26:37 +00:00
|
|
|
inline void fill_cmd_args(std::string &writer, std::string_view args) {
|
2016-09-02 16:20:53 +00:00
|
|
|
char variadic = '\0';
|
|
|
|
int nrep = 0;
|
|
|
|
if (!args.empty() && ((args.back() == 'V') || (args.back() == 'C'))) {
|
|
|
|
variadic = args.back();
|
2021-03-20 01:26:37 +00:00
|
|
|
args.remove_suffix(1);
|
2016-09-02 16:20:53 +00:00
|
|
|
if (!args.empty() && isdigit(args.back())) {
|
|
|
|
nrep = args.back() - '0';
|
2021-03-20 01:26:37 +00:00
|
|
|
args.remove_suffix(1);
|
2016-09-02 16:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (args.empty()) {
|
|
|
|
if (variadic == 'C') {
|
|
|
|
writer += "concat(...)";
|
|
|
|
} else if (variadic == 'V') {
|
|
|
|
writer += "...";
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
int norep = int(args.size()) - nrep;
|
|
|
|
if (norep > 0) {
|
|
|
|
for (int i = 0; i < norep; ++i) {
|
|
|
|
if (i != 0) {
|
|
|
|
writer += ", ";
|
|
|
|
}
|
2021-03-20 01:26:37 +00:00
|
|
|
writer += get_arg_type(args.front());
|
|
|
|
args.remove_prefix(1);
|
2016-09-02 16:20:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (variadic) {
|
|
|
|
if (norep > 0) {
|
|
|
|
writer += ", ";
|
|
|
|
}
|
|
|
|
if (variadic == 'C') {
|
|
|
|
writer += "concat(";
|
|
|
|
}
|
|
|
|
if (!args.empty()) {
|
|
|
|
if (args.size() > 1) {
|
|
|
|
writer += '{';
|
|
|
|
}
|
2017-01-30 18:38:11 +00:00
|
|
|
for (std::size_t i = 0; i < args.size(); ++i) {
|
2016-09-02 16:20:53 +00:00
|
|
|
if (i) {
|
|
|
|
writer += ", ";
|
|
|
|
}
|
|
|
|
writer += get_arg_type(args[i]);
|
|
|
|
}
|
|
|
|
if (args.size() > 1) {
|
|
|
|
writer += '}';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
writer += "...";
|
|
|
|
if (variadic == 'C') {
|
|
|
|
writer += ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 22:29:32 +00:00
|
|
|
inline cs::command *get_hint_cmd(cs::state &cs, std::string_view buf) {
|
2021-03-20 01:26:37 +00:00
|
|
|
std::string_view nextchars = "([;";
|
|
|
|
auto lp = buf.find_first_of(nextchars);
|
|
|
|
if (lp != buf.npos) {
|
2021-03-23 22:29:32 +00:00
|
|
|
cs::command *cmd = get_hint_cmd(cs, buf.substr(1, buf.size() - 1));
|
2016-09-02 16:20:53 +00:00
|
|
|
if (cmd) {
|
|
|
|
return cmd;
|
|
|
|
}
|
|
|
|
}
|
2021-03-20 01:26:37 +00:00
|
|
|
std::size_t nsp = 0;
|
|
|
|
for (auto c: buf) {
|
|
|
|
if (!isspace(c)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++nsp;
|
2016-09-02 16:20:53 +00:00
|
|
|
}
|
2021-03-20 01:26:37 +00:00
|
|
|
buf.remove_prefix(nsp);
|
|
|
|
std::string_view spaces = " \t\r\n";
|
|
|
|
auto p = buf.find_first_of(spaces);
|
|
|
|
if (p != buf.npos) {
|
|
|
|
buf = buf.substr(0, p);
|
2016-09-02 16:20:53 +00:00
|
|
|
}
|
|
|
|
if (!buf.empty()) {
|
2016-09-11 21:33:02 +00:00
|
|
|
auto cmd = cs.get_ident(buf);
|
2021-04-24 22:44:36 +00:00
|
|
|
if (cmd && cmd->is_command()) {
|
|
|
|
return static_cast<cs::command *>(cmd);
|
|
|
|
}
|
2016-09-02 16:20:53 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-09-07 20:57:28 +00:00
|
|
|
#include "edit_linenoise.hh"
|
|
|
|
#include "edit_fallback.hh"
|
2016-09-01 16:42:28 +00:00
|
|
|
|
2016-09-07 20:46:22 +00:00
|
|
|
/* usage */
|
|
|
|
|
2021-03-20 01:26:37 +00:00
|
|
|
void print_usage(std::string_view progname, bool err) {
|
2021-03-20 07:22:15 +00:00
|
|
|
std::fprintf(
|
|
|
|
err ? stderr : stdout,
|
|
|
|
"Usage: %s [options] [file]\n"
|
2016-09-07 20:46:22 +00:00
|
|
|
"Options:\n"
|
|
|
|
" -e str run string \"str\"\n"
|
|
|
|
" -i enter interactive mode after the above\n"
|
|
|
|
" -v show version information\n"
|
|
|
|
" -h show this message\n"
|
|
|
|
" -- stop handling options\n"
|
|
|
|
" - execute stdin and stop handling options"
|
2021-03-20 07:22:15 +00:00
|
|
|
"\n",
|
|
|
|
progname.data()
|
2016-09-07 20:46:22 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void print_version() {
|
2021-03-20 07:22:15 +00:00
|
|
|
printf("%s\n", version.data());
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 22:29:32 +00:00
|
|
|
static cs::state *scs = nullptr;
|
2016-09-05 19:50:24 +00:00
|
|
|
static void do_sigint(int n) {
|
|
|
|
/* in case another SIGINT happens, terminate normally */
|
|
|
|
signal(n, SIG_DFL);
|
2021-03-30 23:10:58 +00:00
|
|
|
scs->set_call_hook([](cs::state &css) {
|
|
|
|
css.set_call_hook(nullptr);
|
|
|
|
throw cs::error{css, "<execution interrupted>"};
|
2016-09-11 21:33:02 +00:00
|
|
|
});
|
2016-09-05 19:50:24 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 22:29:32 +00:00
|
|
|
static bool do_run_file(
|
|
|
|
cs::state &cs, std::string_view fname, cs::any_value &ret
|
|
|
|
) {
|
2021-03-20 07:22:15 +00:00
|
|
|
FILE *f = std::fopen(fname.data(), "rb");
|
|
|
|
if (!f) {
|
2021-03-20 04:09:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-03-20 07:22:15 +00:00
|
|
|
std::fseek(f, 0, SEEK_END);
|
|
|
|
auto len = std::ftell(f);
|
|
|
|
std::fseek(f, 0, SEEK_SET);
|
|
|
|
|
|
|
|
auto buf = std::make_unique<char[]>(len + 1);
|
2021-03-20 04:09:49 +00:00
|
|
|
if (!buf) {
|
2021-03-20 07:22:15 +00:00
|
|
|
std::fclose(f);
|
2021-03-20 04:09:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-03-20 07:22:15 +00:00
|
|
|
if (std::fread(buf.get(), 1, len, f) != std::size_t(len)) {
|
|
|
|
std::fclose(f);
|
2021-03-20 04:09:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-03-20 07:22:15 +00:00
|
|
|
|
2021-03-20 04:09:49 +00:00
|
|
|
buf[len] = '\0';
|
|
|
|
|
2021-04-05 16:32:45 +00:00
|
|
|
ret = cs.run(std::string_view{buf.get(), std::size_t(len)}, fname);
|
2021-03-20 04:09:49 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-03-23 22:29:32 +00:00
|
|
|
static bool do_call(cs::state &cs, std::string_view line, bool file = false) {
|
2021-04-11 01:32:14 +00:00
|
|
|
cs::any_value ret{};
|
2016-09-11 21:33:02 +00:00
|
|
|
scs = &cs;
|
2016-09-05 19:50:24 +00:00
|
|
|
signal(SIGINT, do_sigint);
|
2016-09-13 21:46:51 +00:00
|
|
|
try {
|
2016-09-07 20:46:22 +00:00
|
|
|
if (file) {
|
2021-03-20 04:09:49 +00:00
|
|
|
if (!do_run_file(cs, line, ret)) {
|
2021-03-20 07:22:15 +00:00
|
|
|
std::fprintf(stderr, "cannot read file: %s\n", line.data());
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-04-05 16:32:45 +00:00
|
|
|
ret = cs.run(line);
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
2021-03-23 22:29:32 +00:00
|
|
|
} catch (cs::error const &e) {
|
2016-09-05 19:50:24 +00:00
|
|
|
signal(SIGINT, SIG_DFL);
|
2016-09-11 21:33:02 +00:00
|
|
|
scs = nullptr;
|
2021-03-20 01:26:37 +00:00
|
|
|
std::string_view terr = e.what();
|
|
|
|
auto col = terr.find(':');
|
2016-09-15 18:55:58 +00:00
|
|
|
bool is_lnum = false;
|
2021-03-20 01:26:37 +00:00
|
|
|
if (col != terr.npos) {
|
|
|
|
auto pre = terr.substr(0, col);
|
|
|
|
auto it = std::find_if(
|
|
|
|
pre.begin(), pre.end(),
|
2017-03-31 01:18:26 +00:00
|
|
|
[](auto c) { return !isdigit(c); }
|
2021-03-20 01:26:37 +00:00
|
|
|
);
|
|
|
|
is_lnum = (it == pre.end());
|
|
|
|
terr = terr.substr(col + 2, terr.size() - col - 2);
|
2016-09-10 14:22:27 +00:00
|
|
|
}
|
|
|
|
if (!file && ((terr == "missing \"]\"") || (terr == "missing \")\""))) {
|
2016-09-10 13:13:07 +00:00
|
|
|
return true;
|
|
|
|
}
|
2021-03-20 07:22:15 +00:00
|
|
|
std::printf(
|
|
|
|
"%s%s\n", !is_lnum ? "stdin: " : "stdin:", e.what().data()
|
|
|
|
);
|
2016-09-13 21:46:51 +00:00
|
|
|
if (e.get_stack().get()) {
|
2021-03-20 06:24:25 +00:00
|
|
|
std::string str;
|
2021-03-23 22:29:32 +00:00
|
|
|
cs::print_stack(std::back_inserter(str), e.get_stack());
|
2021-03-20 07:22:15 +00:00
|
|
|
std::printf("%s\n", str.data());
|
2016-09-10 18:45:04 +00:00
|
|
|
}
|
2016-09-10 13:13:07 +00:00
|
|
|
return false;
|
2016-09-05 19:50:24 +00:00
|
|
|
}
|
|
|
|
signal(SIGINT, SIG_DFL);
|
2016-09-11 21:33:02 +00:00
|
|
|
scs = nullptr;
|
2021-03-23 22:29:32 +00:00
|
|
|
if (ret.get_type() != cs::value_type::NONE) {
|
2021-04-11 01:32:14 +00:00
|
|
|
std::printf("%s\n", std::string_view{ret.get_string(cs)}.data());
|
2016-09-05 19:50:24 +00:00
|
|
|
}
|
2016-09-10 13:13:07 +00:00
|
|
|
return false;
|
2016-09-05 19:50:24 +00:00
|
|
|
}
|
|
|
|
|
2021-03-23 22:29:32 +00:00
|
|
|
static void do_tty(cs::state &cs) {
|
2021-04-11 18:49:26 +00:00
|
|
|
auto &prompt = cs.new_var("PROMPT", "> ");
|
|
|
|
auto &prompt2 = cs.new_var("PROMPT2", ">> ");
|
2016-09-01 16:42:28 +00:00
|
|
|
|
|
|
|
bool do_exit = false;
|
2016-09-14 22:42:19 +00:00
|
|
|
cs.new_command("quit", "", [&do_exit](auto &, auto, auto &) {
|
2016-09-01 16:42:28 +00:00
|
|
|
do_exit = true;
|
|
|
|
});
|
|
|
|
|
2021-03-20 07:22:15 +00:00
|
|
|
std::printf("%s (REPL mode)\n", version.data());
|
2016-09-01 16:42:28 +00:00
|
|
|
for (;;) {
|
2016-09-11 21:33:02 +00:00
|
|
|
auto line = read_line(cs, prompt);
|
2016-09-01 16:42:28 +00:00
|
|
|
if (!line) {
|
|
|
|
return;
|
|
|
|
}
|
2017-01-25 00:57:33 +00:00
|
|
|
auto lv = std::move(line.value());
|
2016-09-01 16:42:28 +00:00
|
|
|
if (lv.empty()) {
|
|
|
|
continue;
|
|
|
|
}
|
2016-09-10 13:13:07 +00:00
|
|
|
while ((lv.back() == '\\') || do_call(cs, lv)) {
|
|
|
|
bool bsl = (lv.back() == '\\');
|
|
|
|
if (bsl) {
|
|
|
|
lv.resize(lv.size() - 1);
|
|
|
|
}
|
2016-09-11 21:33:02 +00:00
|
|
|
auto line2 = read_line(cs, prompt2);
|
2016-09-01 16:42:28 +00:00
|
|
|
if (!line2) {
|
|
|
|
return;
|
|
|
|
}
|
2016-09-10 14:22:27 +00:00
|
|
|
if (!bsl || (line2.value() == "\\")) {
|
2016-09-10 13:13:07 +00:00
|
|
|
lv += '\n';
|
|
|
|
}
|
2016-09-01 16:42:28 +00:00
|
|
|
lv += line2.value();
|
|
|
|
}
|
2016-09-11 21:33:02 +00:00
|
|
|
add_history(cs, lv);
|
2016-09-01 16:42:28 +00:00
|
|
|
if (do_exit) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-07 20:46:22 +00:00
|
|
|
int main(int argc, char **argv) {
|
2021-03-23 22:29:32 +00:00
|
|
|
cs::state gcs;
|
2021-04-11 17:36:20 +00:00
|
|
|
cs::std_init_all(gcs);
|
2016-09-07 20:46:22 +00:00
|
|
|
|
2021-04-04 17:35:45 +00:00
|
|
|
/* this is how you can override a setter for variables; fvar and svar
|
|
|
|
* work equivalently - in this case we want to allow multiple values
|
|
|
|
* to be set, but you may also not be using standard i/o and so on
|
|
|
|
*/
|
2021-04-04 00:33:28 +00:00
|
|
|
gcs.new_command("//ivar", "$iiiN", [](auto &css, auto args, auto &) {
|
2021-04-24 22:44:36 +00:00
|
|
|
auto &iv = static_cast<cs::integer_var &>(args[0].get_ident(css));
|
2021-04-05 22:54:46 +00:00
|
|
|
auto nargs = args[4].get_integer();
|
2021-04-03 01:14:52 +00:00
|
|
|
if (nargs <= 1) {
|
2021-04-24 22:44:36 +00:00
|
|
|
auto val = iv.get_value();
|
2021-04-03 01:14:52 +00:00
|
|
|
if ((val >= 0) && (val < 0xFFFFFF)) {
|
|
|
|
std::printf(
|
|
|
|
"%s = %d (0x%.6X: %d, %d, %d)\n",
|
2021-04-24 22:44:36 +00:00
|
|
|
iv.get_name().data(), val, val,
|
2021-04-03 01:14:52 +00:00
|
|
|
(val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF
|
|
|
|
);
|
|
|
|
} else {
|
2021-04-24 22:44:36 +00:00
|
|
|
std::printf("%s = %d\n", iv.get_name().data(), val);
|
2021-04-03 01:14:52 +00:00
|
|
|
}
|
2021-04-04 00:33:28 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (nargs == 2) {
|
2021-04-24 22:44:36 +00:00
|
|
|
iv.set_value(css, args[1].get_integer());
|
2021-04-03 01:14:52 +00:00
|
|
|
} else if (nargs == 3) {
|
2021-04-24 22:44:36 +00:00
|
|
|
iv.set_value(
|
2021-04-05 22:54:46 +00:00
|
|
|
css, (args[1].get_integer() << 8) |
|
|
|
|
(args[2].get_integer() << 16)
|
2021-04-03 01:14:52 +00:00
|
|
|
);
|
|
|
|
} else {
|
2021-04-24 22:44:36 +00:00
|
|
|
iv.set_value(
|
2021-04-05 22:54:46 +00:00
|
|
|
css, args[1].get_integer() | (args[2].get_integer() << 8) |
|
|
|
|
(args[3].get_integer() << 16)
|
2021-04-03 01:14:52 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-24 21:33:19 +00:00
|
|
|
gcs.new_command("//var_changed", "$", [](auto &css, auto args, auto &) {
|
2021-04-04 02:30:36 +00:00
|
|
|
std::printf(
|
2021-04-24 21:33:19 +00:00
|
|
|
"changed var trigger: %s\n",
|
|
|
|
args[0].get_ident(css).get_name().data()
|
2021-04-04 02:30:36 +00:00
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2021-03-30 23:10:58 +00:00
|
|
|
gcs.new_command("exec", "s", [](auto &css, auto args, auto &) {
|
2021-04-11 01:32:14 +00:00
|
|
|
auto file = args[0].get_string(css);
|
|
|
|
cs::any_value val{};
|
2021-03-30 23:10:58 +00:00
|
|
|
bool ret = do_run_file(css, file, val);
|
2016-09-07 20:46:22 +00:00
|
|
|
if (!ret) {
|
2021-03-23 22:29:32 +00:00
|
|
|
throw cs::error(
|
2021-03-30 23:10:58 +00:00
|
|
|
css, "could not run file \"%s\"", file.data()
|
2016-09-15 19:27:14 +00:00
|
|
|
);
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-04-11 01:32:14 +00:00
|
|
|
gcs.new_command("echo", "C", [](auto &css, auto args, auto &) {
|
|
|
|
std::printf("%s\n", std::string_view{args[0].get_string(css)}.data());
|
2016-09-07 20:46:22 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
int firstarg = 0;
|
2016-10-06 18:29:07 +00:00
|
|
|
bool has_inter = false, has_ver = false, has_help = false;
|
|
|
|
char const *has_str = nullptr;
|
2016-09-07 20:46:22 +00:00
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
|
|
if (argv[i][0] != '-') {
|
|
|
|
firstarg = i;
|
|
|
|
goto endargs;
|
|
|
|
}
|
|
|
|
switch (argv[i][1]) {
|
|
|
|
case '-':
|
|
|
|
if (argv[i][2] != '\0') {
|
|
|
|
firstarg = -1;
|
|
|
|
goto endargs;
|
|
|
|
}
|
|
|
|
firstarg = (argv[i + 1] != nullptr) ? (i + 1) : 0;
|
|
|
|
goto endargs;
|
|
|
|
case '\0':
|
|
|
|
firstarg = i;
|
|
|
|
goto endargs;
|
|
|
|
case 'i':
|
|
|
|
if (argv[i][2] != '\0') {
|
|
|
|
firstarg = -1;
|
|
|
|
goto endargs;
|
|
|
|
}
|
|
|
|
has_inter = true;
|
|
|
|
break;
|
|
|
|
case 'v':
|
|
|
|
if (argv[i][2] != '\0') {
|
|
|
|
firstarg = -1;
|
|
|
|
goto endargs;
|
|
|
|
}
|
|
|
|
has_ver = true;
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
if (argv[i][2] != '\0') {
|
|
|
|
firstarg = -1;
|
|
|
|
goto endargs;
|
|
|
|
}
|
|
|
|
has_help = true;
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
if (argv[i][2] == '\0') {
|
|
|
|
++i;
|
|
|
|
if (!argv[i]) {
|
|
|
|
firstarg = -1;
|
|
|
|
goto endargs;
|
2016-10-06 18:29:07 +00:00
|
|
|
} else {
|
|
|
|
has_str = argv[i];
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
2016-10-06 18:29:07 +00:00
|
|
|
} else {
|
|
|
|
has_str = argv[i] + 2;
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
firstarg = -1;
|
|
|
|
goto endargs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endargs:
|
|
|
|
if (firstarg < 0) {
|
|
|
|
print_usage(argv[0], true);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (has_ver && !has_inter) {
|
|
|
|
print_version();
|
|
|
|
}
|
|
|
|
if (has_help) {
|
|
|
|
print_usage(argv[0], false);
|
|
|
|
return 0;
|
|
|
|
}
|
2016-10-06 18:29:07 +00:00
|
|
|
if (has_str) {
|
|
|
|
do_call(gcs, has_str);
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
if (firstarg) {
|
2016-09-11 21:33:02 +00:00
|
|
|
do_call(gcs, argv[firstarg], true);
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
if (!firstarg && !has_str && !has_ver) {
|
|
|
|
if (stdin_is_tty()) {
|
2016-09-11 21:33:02 +00:00
|
|
|
init_lineedit(gcs, argv[0]);
|
|
|
|
do_tty(gcs);
|
2016-09-07 20:46:22 +00:00
|
|
|
return 0;
|
|
|
|
} else {
|
2017-01-30 00:18:55 +00:00
|
|
|
std::string str;
|
2021-03-31 00:21:32 +00:00
|
|
|
for (int c = '\0'; (c = std::fgetc(stdin)) != EOF;) {
|
|
|
|
str += char(c);
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
2016-09-11 21:33:02 +00:00
|
|
|
do_call(gcs, str);
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (has_inter) {
|
|
|
|
if (stdin_is_tty()) {
|
2016-09-11 21:33:02 +00:00
|
|
|
init_lineedit(gcs, argv[0]);
|
|
|
|
do_tty(gcs);
|
2016-09-07 20:46:22 +00:00
|
|
|
}
|
|
|
|
return 0;
|
2016-09-01 16:42:28 +00:00
|
|
|
}
|
|
|
|
}
|