X-Git-Url: https://git.saurik.com/cycript.git/blobdiff_plain/b6d0605d27499279414e2433fae470302c99c110..aff874250f2381788739ce0e6b5717ba1907e624:/Console.cpp diff --git a/Console.cpp b/Console.cpp index 25f624e..8e1c0da 100644 --- a/Console.cpp +++ b/Console.cpp @@ -1,4 +1,4 @@ -/* Cycript - Remove Execution Server and Disassembler +/* Cycript - Inlining/Optimizing JavaScript Compiler * Copyright (C) 2009 Jay Freeman (saurik) */ @@ -37,18 +37,28 @@ */ /* }}} */ -#define _GNU_SOURCE - -#include #include "cycript.hpp" +#ifdef CY_EXECUTE +#include "JavaScript.hpp" +#endif + #include #include #include +#ifdef HAVE_READLINE_H +#include +#else #include +#endif + +#ifdef HAVE_HISTORY_H +#include +#else #include +#endif #include @@ -65,33 +75,87 @@ #include #include #include +#include + +#include + +#include + +static volatile enum { + Working, + Parsing, + Running, + Sending, + Waiting, +} mode_; static jmp_buf ctrlc_; static void sigint(int) { - longjmp(ctrlc_, 1); + switch (mode_) { + case Working: + return; + case Parsing: + longjmp(ctrlc_, 1); + case Running: + throw "*** Ctrl-C"; + case Sending: + return; + case Waiting: + return; + } } -void Run(int socket, const char *data, size_t size, FILE *fout, bool expand = false) { +#if YYDEBUG +static bool bison_; +#endif +static bool strict_; +static bool pretty_; + +void Setup(CYDriver &driver, cy::parser &parser) { +#if YYDEBUG + if (bison_) + parser.set_debug_level(1); +#endif + if (strict_) + driver.strict_ = true; +} + +void Setup(CYOutput &out, CYDriver &driver, CYOptions &options) { + out.pretty_ = pretty_; + CYContext context(driver.pool_, options); + driver.program_->Replace(context); +} + +void Run(int client, const char *data, size_t size, FILE *fout = NULL, bool expand = false) { CYPool pool; const char *json; - if (socket == -1) { + if (client == -1) { + mode_ = Running; +#ifdef CY_EXECUTE json = CYExecute(pool, data); +#else + json = NULL; +#endif + mode_ = Working; if (json != NULL) size = strlen(json); } else { - CYSendAll(socket, &size, sizeof(size)); - CYSendAll(socket, data, size); - CYRecvAll(socket, &size, sizeof(size)); + mode_ = Sending; + CYSendAll(client, &size, sizeof(size)); + CYSendAll(client, data, size); + mode_ = Waiting; + CYRecvAll(client, &size, sizeof(size)); if (size == _not(size_t)) json = NULL; else { char *temp(new(pool) char[size + 1]); - CYRecvAll(socket, temp, size); + CYRecvAll(client, temp, size); temp[size] = '\0'; json = temp; } + mode_ = Working; } if (json != NULL && fout != NULL) { @@ -120,11 +184,26 @@ void Run(int socket, const char *data, size_t size, FILE *fout, bool expand = fa } } -void Run(int socket, std::string &code, FILE *fout, bool expand = false) { - Run(socket, code.c_str(), code.size(), fout, expand); +void Run(int client, std::string &code, FILE *fout = NULL, bool expand = false) { + Run(client, code.c_str(), code.size(), fout, expand); } -static void Console(int socket) { +int (*append_history$)(int, const char *); + +static void Console(apr_pool_t *pool, int client, CYOptions &options) { + passwd *passwd; + if (const char *username = getenv("LOGNAME")) + passwd = getpwnam(username); + else + passwd = getpwuid(getuid()); + + const char *basedir(apr_psprintf(pool, "%s/.cycript", passwd->pw_dir)); + const char *histfile(apr_psprintf(pool, "%s/history", basedir)); + size_t histlines(0); + + mkdir(basedir, 0700); + read_history(histfile); + bool bypass(false); bool debug(false); bool expand(false); @@ -147,15 +226,20 @@ static void Console(int socket) { const char *prompt("cy# "); if (setjmp(ctrlc_) != 0) { + mode_ = Working; fputs("\n", fout); fflush(fout); goto restart; } read: + mode_ = Parsing; char *line(readline(prompt)); + mode_ = Working; if (line == NULL) break; + if (line[0] == '\0') + goto read; if (!extra) { extra = true; @@ -175,12 +259,22 @@ static void Console(int socket) { fflush(fout); } add_history(line); + ++histlines; goto restart; } } - lines.push_back(line); command += line; + + char *begin(line), *end(line + strlen(line)); + while (char *nl = reinterpret_cast(memchr(begin, '\n', end - begin))) { + *nl = '\0'; + lines.push_back(begin); + begin = nl + 1; + } + + lines.push_back(begin); + free(line); std::string code; @@ -190,6 +284,7 @@ static void Console(int socket) { else { CYDriver driver(""); cy::parser parser(driver); + Setup(driver, parser); driver.data_ = command.c_str(); driver.size_ = command.size(); @@ -197,23 +292,28 @@ static void Console(int socket) { if (parser.parse() != 0 || !driver.errors_.empty()) { for (CYDriver::Errors::const_iterator error(driver.errors_.begin()); error != driver.errors_.end(); ++error) { cy::position begin(error->location_.begin); - if (begin.line != lines.size() || begin.column - 1 != lines.back().size()) { + if (begin.line != lines.size() || begin.column - 1 != lines.back().size() || error->warning_) { cy::position end(error->location_.end); + if (begin.line != lines.size()) { std::cerr << " | "; std::cerr << lines[begin.line - 1] << std::endl; } - std::cerr << " | "; + + std::cerr << "...."; for (size_t i(0); i != begin.column - 1; ++i) std::cerr << '.'; - if (begin.line != end.line) + if (begin.line != end.line || begin.column == end.column) std::cerr << '^'; else for (size_t i(0), e(end.column - begin.column); i != e; ++i) std::cerr << '^'; std::cerr << std::endl; + std::cerr << " | "; std::cerr << error->message_ << std::endl; + add_history(command.c_str()); + ++histlines; goto restart; } } @@ -225,24 +325,34 @@ static void Console(int socket) { goto read; } - if (driver.source_ == NULL) + if (driver.program_ == NULL) goto restart; - if (socket != -1) + if (client != -1) code = command; else { std::ostringstream str; - driver.source_->Show(str); + CYOutput out(str, options); + Setup(out, driver, options); + out << *driver.program_; code = str.str(); } } add_history(command.c_str()); + ++histlines; if (debug) std::cout << code << std::endl; - Run(socket, code, fout, expand); + Run(client, code, fout, expand); + } + + if (append_history$ != NULL) { + _syscall(close(_syscall(open(histfile, O_CREAT | O_WRONLY, 0600)))); + (*append_history$)(histlines, histfile); + } else { + write_history(histfile); } fputs("\n", fout); @@ -266,94 +376,272 @@ static void *Map(const char *path, size_t *psize) { return base; } -int main(int argc, char *argv[]) { +void InjectLibrary(pid_t pid); + +int Main(int argc, char const * const argv[], char const * const envp[]) { + bool tty(isatty(STDIN_FILENO)); + bool compile(false); + CYOptions options; + + append_history$ = reinterpret_cast(dlsym(RTLD_DEFAULT, "append_history")); + +#ifdef CY_ATTACH pid_t pid(_not(pid_t)); +#endif - for (;;) switch (getopt(argc, argv, "p:")) { - case -1: - goto getopt; - case '?': - fprintf(stderr, "usage: cycript [-p ] [