/* Cycript - Optimizing JavaScript Compiler/Runtime
- * Copyright (C) 2009-2013 Jay Freeman (saurik)
+ * Copyright (C) 2009-2015 Jay Freeman (saurik)
*/
-/* GNU General Public License, Version 3 {{{ */
+/* GNU Affero General Public License, Version 3 {{{ */
/*
- * Cycript is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation, either version 3 of the License,
- * or (at your option) any later version.
- *
- * Cycript is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Cycript. If not, see <http://www.gnu.org/licenses/>.
+ * GNU Affero General Public License for more details.
+
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
**/
/* }}} */
#endif
#include <errno.h>
+#include <getopt.h>
+#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <pwd.h>
-#include <apr_getopt.h>
-#include <apr_pools.h>
-#include <apr_strings.h>
-
#include <dlfcn.h>
#include "Display.hpp"
case Parsing:
longjmp(ctrlc_, 1);
case Running:
- throw "*** Ctrl-C";
+ CYCancel();
+ return;
case Sending:
return;
case Waiting:
CYOptions options;
CYContext context(options);
- CYStatement *statement(driver.program_->statements_);
+ CYStatement *statement(driver.program_->code_);
_assert(statement != NULL);
_assert(statement->next_ == NULL);
- CYExpress *express(dynamic_cast<CYExpress *>(driver.program_->statements_));
+ CYExpress *express(dynamic_cast<CYExpress *>(driver.program_->code_));
_assert(express != NULL);
- return express->expression_;
+ CYParenthetical *parenthetical(dynamic_cast<CYParenthetical *>(express->expression_));
+ _assert(parenthetical != NULL);
+
+ return parenthetical->expression_;
}
static int client_;
static char **Complete(const char *word, int start, int end) {
- rl_attempted_completion_over = TRUE;
+ rl_attempted_completion_over = ~0;
CYLocalPool pool;
driver.program_->Replace(context);
- std::ostringstream str;
+ std::stringbuf str;
CYOutput out(str, options);
out << *driver.program_;
// need char *, not const char *
static char name_[] = "cycript";
-static char break_[] = " \t\n\"\\'`@$><=;|&{(" ")}" ".:[]";
+static char break_[] = " \t\n\"\\'`@><=;|&{(" ")}" ".:[]";
class History {
private:
~History() {
if (append_history$ != NULL) {
- _syscall(close(_syscall(open(histfile_.c_str(), O_CREAT | O_WRONLY, 0600))));
+ int fd(_syscall(open(histfile_.c_str(), O_CREAT | O_WRONLY, 0600)));
+ _syscall(close(fd));
_assert((*append_history$)(histlines_, histfile_.c_str()) == 0);
} else {
_assert(write_history(histfile_.c_str()) == 0);
};
static void Console(CYOptions &options) {
- CYPool pool;
-
- passwd *passwd;
- if (const char *username = getenv("LOGNAME"))
- passwd = getpwnam(username);
- else
- passwd = getpwuid(getuid());
+ std::string basedir;
+ if (const char *home = getenv("HOME"))
+ basedir = home;
+ else {
+ passwd *passwd;
+ if (const char *username = getenv("LOGNAME"))
+ passwd = getpwnam(username);
+ else
+ passwd = getpwuid(getuid());
+ basedir = passwd->pw_dir;
+ }
- std::string basedir(passwd->pw_dir);
basedir += "/.cycript";
mkdir(basedir.c_str(), 0700);
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);
+ CYPosition begin(error->location_.begin);
if (begin.line != lines.size() || begin.column < lines.back().size() || error->warning_) {
- cy::position end(error->location_.end);
+ CYPosition end(error->location_.end);
if (begin.line != lines.size()) {
std::cerr << " | ";
if (driver.program_ == NULL)
goto restart;
- std::ostringstream str;
+ std::stringbuf str;
CYOutput out(str, options);
Setup(out, driver, options, lower);
out << *driver.program_;
}
}
-void InjectLibrary(pid_t pid);
-
-int Main(int argc, char const * const argv[], char const * const envp[]) {
- _aprcall(apr_initialize());
-
- apr_pool_t *pool;
- apr_pool_create(&pool, NULL);
+void InjectLibrary(pid_t, int, const char *[]);
+int Main(int argc, char * const argv[], char const * const envp[]) {
bool tty(isatty(STDIN_FILENO));
bool compile(false);
bool target(false);
const char *host(NULL);
const char *port(NULL);
- apr_getopt_t *state;
- _aprcall(apr_getopt_init(&state, pool, argc, argv));
+ optind = 1;
for (;;) {
- int opt;
- const char *arg;
-
- apr_status_t status(apr_getopt_long(state, (apr_getopt_option_t[]) {
- {NULL, 'c', false, NULL},
- {NULL, 'g', true, NULL},
- {NULL, 'n', true, NULL},
+ int option(getopt_long(argc, argv,
+ "c"
+ "g:"
+ "n:"
#ifdef CY_ATTACH
- {NULL, 'p', true, NULL},
+ "p:"
#endif
- {NULL, 'r', true, NULL},
- {NULL, 's', false, NULL},
- {0, 0, 0, 0}}, &opt, &arg));
+ "r:"
+ "s"
+ , (const struct option[]) {
+ {NULL, no_argument, NULL, 'c'},
+ {NULL, required_argument, NULL, 'g'},
+ {NULL, required_argument, NULL, 'n'},
+#ifdef CY_ATTACH
+ {NULL, required_argument, NULL, 'p'},
+#endif
+ {NULL, required_argument, NULL, 'r'},
+ {NULL, no_argument, NULL, 's'},
+ {0, 0, 0, 0}}, NULL));
- switch (status) {
- case APR_EOF:
+ switch (option) {
+ case -1:
goto getopt;
- case APR_BADCH:
- case APR_BADARG:
+
+ case ':':
+ case '?':
fprintf(stderr,
"usage: cycript [-c]"
#ifdef CY_ATTACH
" [<script> [<arg>...]]\n"
);
return 1;
- default:
- _aprcall(status);
- }
- switch (opt) {
target:
if (!target)
target = true;
case 'g':
if (false);
- else if (strcmp(arg, "rename") == 0)
+ else if (strcmp(optarg, "rename") == 0)
options.verbose_ = true;
#if YYDEBUG
- else if (strcmp(arg, "bison") == 0)
+ else if (strcmp(optarg, "bison") == 0)
bison_ = true;
#endif
else {
case 'n':
if (false);
- else if (strcmp(arg, "minify") == 0)
+ else if (strcmp(optarg, "minify") == 0)
pretty_ = true;
else {
fprintf(stderr, "invalid name for -n\n");
#ifdef CY_ATTACH
case 'p': {
- size_t size(strlen(arg));
+ size_t size(strlen(optarg));
char *end;
- pid = strtoul(arg, &end, 0);
- if (arg + size != end) {
+ pid = strtoul(optarg, &end, 0);
+ if (optarg + size != end) {
// XXX: arg needs to be escaped in some horrendous way of doom
- const char *command(apr_pstrcat(pool, "ps axc|sed -e '/^ *[0-9]/{s/^ *\\([0-9]*\\)\\( *[^ ]*\\)\\{3\\} *-*\\([^ ]*\\)/\\3 \\1/;/^", arg, " /{s/^[^ ]* //;q;};};d'", NULL));
+ // XXX: this is a memory leak now because I just don't care enough
+ char *command;
+ asprintf(&command, "ps axc|sed -e '/^ *[0-9]/{s/^ *\\([0-9]*\\)\\( *[^ ]*\\)\\{3\\} *-*\\([^ ]*\\)/\\3 \\1/;/^%s /{s/^[^ ]* //;q;};};d'", optarg);
if (FILE *pids = popen(command, "r")) {
char value[32];
}
if (pid == _not(pid_t)) {
- fprintf(stderr, "unable to find process `%s' using ps\n", arg);
+ fprintf(stderr, "unable to find process `%s' using ps\n", optarg);
return 1;
}
}
#endif
case 'r': {
- //size_t size(strlen(arg));
+ //size_t size(strlen(optarg));
- char *colon(strrchr(arg, ':'));
+ char *colon(strrchr(optarg, ':'));
if (colon == NULL) {
fprintf(stderr, "missing colon in hostspec\n");
return 1;
/*char *end;
port = strtoul(colon + 1, &end, 10);
- if (end != arg + size) {
+ if (end != optarg + size) {
fprintf(stderr, "invalid port in hostspec\n");
return 1;
}*/
- host = arg;
+ host = optarg;
*colon = '\0';
port = colon + 1;
} goto target;
case 's':
strict_ = true;
break;
+
+ default:
+ _assert(false);
}
- } getopt:;
+ }
+
+ getopt:
+ argc -= optind;
+ argv += optind;
const char *script;
- int ind(state->ind);
#ifdef CY_ATTACH
- if (pid != _not(pid_t) && ind < argc - 1) {
+ if (pid != _not(pid_t) && argc > 1) {
fprintf(stderr, "-p cannot set argv\n");
return 1;
}
#endif
- if (ind == argc)
+ if (argc == 0)
script = NULL;
else {
#ifdef CY_EXECUTE
// XXX: const_cast?! wtf gcc :(
- CYSetArgs(argc - ind - 1, const_cast<const char **>(argv + ind + 1));
+ CYSetArgs(argc - 1, const_cast<const char **>(argv + 1));
#endif
- script = argv[ind];
+ script = argv[0];
if (strcmp(script, "-") == 0)
script = NULL;
}
memset(&address, 0, sizeof(address));
address.sun_family = AF_UNIX;
- sprintf(address.sun_path, "/tmp/.s.cy.%u", getpid());
+ const char *tmp;
+#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__))
+ tmp = "/Library/Caches";
+#else
+ tmp = "/tmp";
+#endif
+
+ sprintf(address.sun_path, "%s/.s.cy.%u", tmp, getpid());
unlink(address.sun_path);
struct File {
_syscall(chmod(address.sun_path, 0777));
_syscall(listen(server, 1));
- InjectLibrary(pid);
+ InjectLibrary(pid, 1, (const char *[]) {address.sun_path, NULL});
client_ = _syscall(accept(server, NULL, NULL));
}
#else
for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i)
std::cerr << i->location_.begin << ": " << i->message_ << std::endl;
} else if (driver.program_ != NULL) {
- std::ostringstream str;
+ std::stringbuf str;
CYOutput out(str, options);
Setup(out, driver, options, true);
out << *driver.program_;
}
}
- apr_pool_destroy(pool);
-
return 0;
}
-int main(int argc, char const * const argv[], char const * const envp[]) {
- apr_status_t status(apr_app_initialize(&argc, &argv, &envp));
-
- if (status != APR_SUCCESS) {
- fprintf(stderr, "apr_app_initialize() != APR_SUCCESS\n");
- return 1;
- } else try {
+int main(int argc, char * const argv[], char const * const envp[]) {
+ try {
return Main(argc, argv, envp);
} catch (const CYException &error) {
CYPool pool;