#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"
driver.strict_ = true;
}
-void Setup(CYOutput &out, CYDriver &driver, CYOptions &options) {
+void Setup(CYOutput &out, CYDriver &driver, CYOptions &options, bool lower) {
out.pretty_ = pretty_;
CYContext context(options);
- driver.program_->Replace(context);
+ if (lower)
+ driver.program_->Replace(context);
}
static CYUTF8String Run(CYPool &pool, int client, CYUTF8String code) {
if (client == -1) {
mode_ = Running;
#ifdef CY_EXECUTE
- json = CYExecute(pool, code);
+ json = CYExecute(CYGetJSContext(), pool, code);
#else
json = NULL;
#endif
CYOptions options;
CYContext context(options);
- // XXX: this could be replaced with a CYStatement::Primitive()
- if (CYExpress *express = dynamic_cast<CYExpress *>(driver.program_->statements_))
- return express->expression_->Primitive(context);
+ CYStatement *statement(driver.program_->statements_);
+ _assert(statement != NULL);
+ _assert(statement->next_ == NULL);
- return NULL;
+ CYExpress *express(dynamic_cast<CYExpress *>(driver.program_->statements_));
+ _assert(express != NULL);
+
+ return express->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;
" var before = prefix.length;\n"
" prefix += word;\n"
" var entire = prefix.length;\n"
- " for (name in object)\n"
+ " for (var name in object)\n"
" if (name.substring(0, entire) == prefix)\n"
" names.push(name.substr(before));\n"
" return names;\n"
if (result == NULL)
return NULL;
- CYArray *array(dynamic_cast<CYArray *>(result));
-
+ CYArray *array(dynamic_cast<CYArray *>(result->Primitive(context)));
if (array == NULL) {
*out_ << '\n';
Output(false, json, out_);
~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);
bool bypass(false);
bool debug(false);
bool expand(false);
+ bool lower(true);
bool syntax(true);
out_ = &std::cout;
read:
#if RL_READLINE_VERSION >= 0x0600
- if (syntax) {
- rl_prep_term_function = CYDisplayStart;
+ if (syntax)
rl_redisplay_function = CYDisplayUpdate;
- rl_deprep_term_function = CYDisplayFinish;
- } else {
- rl_prep_term_function = rl_prep_terminal;
+ else
rl_redisplay_function = rl_redisplay;
- rl_deprep_term_function = rl_deprep_terminal;
- }
#endif
mode_ = Parsing;
} else if (data == "debug") {
debug = !debug;
*out_ << "debug == " << (debug ? "true" : "false") << std::endl;
+ } else if (data == "destroy") {
+ CYDestroyContext();
+ } else if (data == "gc") {
+ *out_ << "collecting... " << std::flush;
+ CYGarbageCollect(CYGetJSContext());
+ *out_ << "done." << std::endl;
+ } else if (data == "exit") {
+ return;
} else if (data == "expand") {
expand = !expand;
*out_ << "expand == " << (expand ? "true" : "false") << std::endl;
+ } else if (data == "lower") {
+ lower = !lower;
+ *out_ << "lower == " << (lower ? "true" : "false") << std::endl;
} else if (data == "syntax") {
syntax = !syntax;
*out_ << "syntax == " << (syntax ? "true" : "false") << std::endl;
std::ostringstream str;
CYOutput out(str, options);
- Setup(out, driver, options);
+ Setup(out, driver, options, lower);
out << *driver.program_;
code = str.str();
}
history += command_;
if (debug) {
+ std::cout << "cy= ";
Write(syntax, code.c_str(), code.size(), std::cout);
std::cout << std::endl;
}
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);
-
+int Main(int argc, char * const argv[], char const * const envp[]) {
bool tty(isatty(STDIN_FILENO));
bool compile(false);
+ bool target(false);
CYOptions options;
append_history$ = (int (*)(int, const char *)) (dlsym(RTLD_DEFAULT, "append_history"));
const char *host(NULL);
const char *port(NULL);
- apr_getopt_t *state;
- _aprcall(apr_getopt_init(&state, pool, argc, argv));
+ optind = 1;
for (;;) {
- char opt;
- const char *arg;
-
- apr_status_t status(apr_getopt(state,
- "cg:n:"
+ int option(getopt_long(argc, argv,
+ "c"
+ "g:"
+ "n:"
#ifdef CY_ATTACH
"p:"
#endif
"r:"
"s"
- , &opt, &arg));
+ , (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;
+ else {
+ fprintf(stderr, "only one of -[c"
+#ifdef CY_ATTACH
+ "p"
+#endif
+ "r] may be used at a time\n");
+ return 1;
+ }
+ break;
+
case 'c':
compile = true;
- break;
+ goto target;
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];
break;
else {
size += read;
- if (size == sizeof(value)) {
- pid = _not(pid_t);
+ if (size == sizeof(value))
goto fail;
- }
}
}
}
if (pid == _not(pid_t)) {
- fprintf(stderr, "invalid pid for -p\n");
+ fprintf(stderr, "unable to find process `%s' using ps\n", optarg);
return 1;
}
}
- } break;
+ } goto target;
#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;
- } break;
+ } 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;
}
-
- if (pid != _not(pid_t) && compile) {
- fprintf(stderr, "-p conflicts with -c\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;
}
-#ifdef CY_ATTACH
- if (pid != _not(pid_t) && script == NULL && !tty) {
- fprintf(stderr, "non-terminal attaching to remote console\n");
- return 1;
- }
-#endif
-
#ifdef CY_ATTACH
if (pid == _not(pid_t))
client_ = -1;
else {
- int server(_syscall(socket(PF_UNIX, SOCK_STREAM, 0))); try {
- struct sockaddr_un address;
- memset(&address, 0, sizeof(address));
- address.sun_family = AF_UNIX;
-
- sprintf(address.sun_path, "/tmp/.s.cy.%u", getpid());
-
- _syscall(bind(server, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
- _syscall(chmod(address.sun_path, 0777));
-
- try {
- _syscall(listen(server, 1));
- InjectLibrary(pid);
- client_ = _syscall(accept(server, NULL, NULL));
- } catch (...) {
- // XXX: exception?
- unlink(address.sun_path);
- throw;
+ struct Socket {
+ int fd_;
+
+ Socket(int fd) :
+ fd_(fd)
+ {
}
- } catch (...) {
- _syscall(close(server));
- throw;
- }
+
+ ~Socket() {
+ close(fd_);
+ }
+
+ operator int() {
+ return fd_;
+ }
+ } server(_syscall(socket(PF_UNIX, SOCK_STREAM, 0)));
+
+ struct sockaddr_un address;
+ memset(&address, 0, sizeof(address));
+ address.sun_family = AF_UNIX;
+
+ sprintf(address.sun_path, "/tmp/.s.cy.%u", getpid());
+ unlink(address.sun_path);
+
+ struct File {
+ const char *path_;
+
+ File(const char *path) :
+ path_(path)
+ {
+ }
+
+ ~File() {
+ unlink(path_);
+ }
+ } file(address.sun_path);
+
+ _syscall(bind(server, reinterpret_cast<sockaddr *>(&address), SUN_LEN(&address)));
+ _syscall(chmod(address.sun_path, 0777));
+
+ _syscall(listen(server, 1));
+ InjectLibrary(pid);
+ client_ = _syscall(accept(server, NULL, NULL));
}
#else
client_ = -1;
} else if (driver.program_ != NULL) {
std::ostringstream str;
CYOutput out(str, options);
- Setup(out, driver, options);
+ Setup(out, driver, options, true);
out << *driver.program_;
std::string code(str.str());
if (compile)
}
}
- 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;