-/* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2015 Jay Freeman (saurik)
+/* Cycript - The Truly Universal Scripting Language
+ * Copyright (C) 2009-2016 Jay Freeman (saurik)
*/
/* GNU Affero General Public License, Version 3 {{{ */
return NULL;
}
+static void _lblcall(int (*command)(int, int), int count, int key) {
+ int last(_rl_last_c_pos);
+ // rl_rubout crashes in _rl_erase_at_end_of_line if _rl_last_c_pos != 0
+ if (command == &rl_rubout)
+ _rl_last_c_pos = 0;
+ for (int i(0); i != count; ++i)
+ if (command(1, key) != 0)
+ _assert(false);
+ _rl_last_c_pos = last;
+}
+
static int CYConsoleKeyReturn(int count, int key) {
if (rl_point != rl_end) {
- if (memchr(rl_line_buffer, '\n', rl_end) == NULL)
- return rl_newline(count, key);
+ if (memchr(rl_line_buffer, '\n', rl_end) == NULL) {
+ _lblcall(&rl_newline, count, key);
+ return 0;
+ }
+ insert:
char *before(CYmemrchr(rl_line_buffer, '\n', rl_point));
if (before == NULL)
before = rl_line_buffer;
int adjust(rl_line_buffer + space - 1 - before);
if (space == rl_point && adjust != 0)
- rl_rubout(adjust, '\b');
+ _lblcall(&rl_rubout, adjust, '\b');
- rl_insert(count, '\n');
+ _lblcall(&rl_insert, count, '\n');
if (adjust != 0)
- rl_insert(adjust, ' ');
+ _lblcall(&rl_insert, adjust, ' ');
return 0;
}
else {
std::string command(rl_line_buffer, rl_end);
command += '\n';
- std::istringstream stream(command);
+ std::stringbuf stream(command);
size_t last(std::string::npos);
for (size_t i(0); i != std::string::npos; i = command.find('\n', i + 1))
done = true;
}
- if (done)
- return rl_newline(count, key);
+ if (done) {
+ _lblcall(&rl_newline, count, key);
+ return 0;
+ }
- rl_insert(count, '\n');
- return 0;
+ // XXX: this was the most obvious fix, but is seriously dumb
+ goto insert;
}
static int CYConsoleKeyUp(int count, int key) {
- while (count-- != 0) {
+ for (; count != 0; --count) {
char *after(CYmemrchr(rl_line_buffer, '\n', rl_point));
if (after == NULL) {
if (int value = rl_get_previous_history(1, key))
}
static int CYConsoleKeyDown(int count, int key) {
- while (count-- != 0) {
+ for (; count != 0; --count) {
char *after(static_cast<char *>(memchr(rl_line_buffer + rl_point, '\n', rl_end - rl_point)));
if (after == NULL) {
int where(where_history());
static int CYConsoleLineEnd(int count, int key) {
while (rl_point != rl_end && rl_line_buffer[rl_point] != '\n')
++rl_point;
+ if (rl_point != rl_end && rl_editing_mode == 0)
+ --rl_point;
return 0;
}
static int CYConsoleKeyBack(int count, int key) {
- while (count-- != 0) {
+ for (; count != 0; --count) {
+ if (rl_point == 0)
+ return 1;
+
char *before(CYmemrchr(rl_line_buffer, '\n', rl_point));
- if (before == NULL)
- return rl_rubout(count, key);
+ if (before == NULL) {
+ int adjust(std::min(count, rl_point));
+ _lblcall(&rl_rubout, adjust, key);
+ count -= adjust - 1;
+ continue;
+ }
int start(before + 1 - rl_line_buffer);
if (start == rl_point) rubout: {
- rl_rubout(1, key);
+ _lblcall(&rl_rubout, 1, key);
continue;
}
for (int i(start); i != rl_point; ++i)
if (rl_line_buffer[i] != ' ')
goto rubout;
- rl_rubout((rl_point - start) % 4 ?: 4, key);
+ _lblcall(&rl_rubout, (rl_point - start) % 4 ?: 4, key);
}
return 0;
for (int i(start); i != rl_point; ++i)
if (rl_line_buffer[i] != ' ')
goto complete;
- return rl_insert(4 - (rl_point - start) % 4, ' ');
+ _lblcall(&rl_insert, 4 - (rl_point - start) % 4, ' ');
+ return 0;
}
-static void CYConsoleRemapBind(rl_command_func_t *from, rl_command_func_t *to) {
- char **keyseqs(rl_invoking_keyseqs(from));
+static void CYConsoleRemapBind(Keymap map, rl_command_func_t *from, rl_command_func_t *to) {
+ char **keyseqs(rl_invoking_keyseqs_in_map(from, map));
if (keyseqs == NULL)
return;
for (char **keyseq(keyseqs); *keyseq != NULL; ++keyseq) {
- rl_bind_keyseq(*keyseq, to);
+ rl_bind_keyseq_in_map(*keyseq, to, map);
free(*keyseq);
}
free(keyseqs);
}
+static void CYConsoleRemapKeys(Keymap map) {
+ CYConsoleRemapBind(map, &rl_beg_of_line, &CYConsoleLineBegin);
+ CYConsoleRemapBind(map, &rl_end_of_line, &CYConsoleLineEnd);
+
+ CYConsoleRemapBind(map, &rl_get_previous_history, &CYConsoleKeyUp);
+ CYConsoleRemapBind(map, &rl_get_next_history, &CYConsoleKeyDown);
+
+ CYConsoleRemapBind(map, &rl_rubout, &CYConsoleKeyBack);
+ CYConsoleRemapBind(map, &rl_complete, &CYConsoleKeyTab);
+}
+
static void CYConsolePrepTerm(int meta) {
rl_prep_terminal(meta);
- CYConsoleRemapBind(&rl_beg_of_line, &CYConsoleLineBegin);
- CYConsoleRemapBind(&rl_end_of_line, &CYConsoleLineEnd);
- CYConsoleRemapBind(&rl_rubout, &CYConsoleKeyBack);
+ CYConsoleRemapKeys(emacs_standard_keymap);
+ CYConsoleRemapKeys(emacs_meta_keymap);
+ CYConsoleRemapKeys(emacs_ctlx_keymap);
+ CYConsoleRemapKeys(vi_insertion_keymap);
+ CYConsoleRemapKeys(vi_movement_keymap);
}
static void Console(CYOptions &options) {
rl_completer_word_break_characters = break_;
rl_attempted_completion_function = &Complete;
- rl_bind_key(TAB, &CYConsoleKeyTab);
-
rl_redisplay_function = CYDisplayUpdate;
rl_prep_term_function = CYConsolePrepTerm;
-#if defined (__MSDOS__)
- rl_bind_keyseq("\033[0A", &CYConsoleKeyUp);
- rl_bind_keyseq("\033[0D", &CYConsoleKeyDown);
-#endif
- rl_bind_keyseq("\033[A", &CYConsoleKeyUp);
- rl_bind_keyseq("\033[B", &CYConsoleKeyDown);
- rl_bind_keyseq("\033OA", &CYConsoleKeyUp);
- rl_bind_keyseq("\033OB", &CYConsoleKeyDown);
-#if defined (__MINGW32__)
- rl_bind_keyseq("\340H", &CYConsoleKeyUp);
- rl_bind_keyseq("\340P", &CYConsoleKeyDown);
- rl_bind_keyseq("\\000H", &CYConsoleKeyUp);
- rl_bind_keyseq("\\000P", &CYConsoleKeyDown);
-#endif
-
struct sigaction action;
sigemptyset(&action.sa_mask);
action.sa_handler = &sigint;
free(line);
if (command.empty())
continue;
+ history += command;
if (command[0] == '?') {
std::string data(command.substr(1));
*out_ << "lower == " << (lower ? "true" : "false") << std::endl;
}
- history += command;
continue;
}
std::string code;
if (bypass)
code = command;
- else {
- std::istringstream stream(command);
+ else try {
+ std::stringbuf stream(command);
CYPool pool;
CYDriver driver(pool, stream);
std::cerr << " | ";
std::cerr << error->message_ << std::endl;
- history += command;
break;
}
Setup(out, driver, options, lower);
out << *driver.script_;
code = str.str();
+ } catch (const CYException &error) {
+ CYPool pool;
+ std::cout << error.PoolCString(pool) << std::endl;
+ continue;
}
- history += command;
-
if (debug) {
std::cout << "cy= ";
CYLexerHighlight(code.c_str(), code.size(), std::cout);
stream = new std::istringstream(buffer.str());
CYPool pool;
- CYDriver driver(pool, *stream, script);
+ CYDriver driver(pool, *stream->rdbuf(), script);
Setup(driver);
uint64_t begin(CYGetTime());
}
CYPool pool;
- CYDriver driver(pool, *stream, script);
+ CYDriver driver(pool, *stream->rdbuf(), script);
Setup(driver);
bool failed(driver.Parse());
if (failed || !driver.errors_.empty()) {
for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i)
std::cerr << i->location_.begin << ": " << i->message_ << std::endl;
+ return 1;
} else if (driver.script_ != NULL) {
std::stringbuf str;
CYOutput out(str, options);