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) {
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);
+
+ CYExpress *express(dynamic_cast<CYExpress *>(driver.program_->statements_));
+ _assert(express != NULL);
- return NULL;
+ return express->expression_;
}
static int client_;
" 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_);
bool bypass(false);
bool debug(false);
bool expand(false);
+ bool lower(true);
bool syntax(true);
out_ = &std::cout;
} 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;
}
bool tty(isatty(STDIN_FILENO));
bool compile(false);
+ bool target(false);
CYOptions options;
append_history$ = (int (*)(int, const char *)) (dlsym(RTLD_DEFAULT, "append_history"));
_aprcall(apr_getopt_init(&state, pool, argc, argv));
for (;;) {
- char opt;
+ int opt;
const char *arg;
- apr_status_t status(apr_getopt(state,
- "cg:n:"
+ apr_status_t status(apr_getopt_long(state, (apr_getopt_option_t[]) {
+ {NULL, 'c', false, NULL},
+ {NULL, 'g', true, NULL},
+ {NULL, 'n', true, NULL},
#ifdef CY_ATTACH
- "p:"
+ {NULL, 'p', true, NULL},
#endif
- "r:"
- "s"
- , &opt, &arg));
+ {NULL, 'r', true, NULL},
+ {NULL, 's', false, NULL},
+ {0, 0, 0, 0}}, &opt, &arg));
switch (status) {
case APR_EOF:
}
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);
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", arg);
return 1;
}
}
- } break;
+ } goto target;
#endif
case 'r': {
host = arg;
*colon = '\0';
port = colon + 1;
- } break;
+ } goto target;
case 's':
strict_ = true;
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)
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)