From 057f943fd8f42a4e29e95313dd94ddf236a0996d Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Thu, 1 Oct 2009 20:57:48 +0000 Subject: [PATCH] Readline integration and console refactoring. --- Application.mm | 123 ++++++++++++++++++++++++++++++++++++++++++++++--- Library.mm | 117 ++++------------------------------------------ cycript.h | 36 +++++++++++++++ makefile | 14 ++++-- 4 files changed, 171 insertions(+), 119 deletions(-) create mode 100644 cycript.h diff --git a/Application.mm b/Application.mm index cf84570..4dc765b 100644 --- a/Application.mm +++ b/Application.mm @@ -1,12 +1,121 @@ -#include +#define _GNU_SOURCE + #include +#include "cycript.h" + +#include +#include + +#include + +#include +#include + +#include "Cycript.tab.hh" + +static jmp_buf ctrlc_; + +void sigint(int) { + longjmp(ctrlc_, 1); +} + +int main(int argc, const char *argv[]) { + FILE *fout(stdout); + + rl_bind_key('\t', rl_insert); + + struct sigaction action; + sigemptyset(&action.sa_mask); + action.sa_handler = &sigint; + action.sa_flags = 0; + sigaction(SIGINT, &action, NULL); + + restart: for (;;) { + std::string command; + std::vector lines; + + if (setjmp(ctrlc_) != 0) { + fputs("\n", fout); + fflush(fout); + goto restart; + } + + const char *prompt("cy# "); + read: + char *line(readline(prompt)); + if (line == NULL) + break; + lines.push_back(line); + command += line; + free(line); + + CYDriver driver(""); + cy::parser parser(driver); + + driver.data_ = command.c_str(); + driver.size_ = command.size(); + + if (parser.parse() != 0) { + for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i) { + cy::position begin(i->location_.begin); + if (begin.line != lines.size() || begin.column - 1 != lines.back().size()) { + std::cerr << i->message_ << std::endl; + goto restart; + } + } + + driver.errors_.clear(); + + command += '\n'; + prompt = "cy> "; + goto read; + } + + if (driver.source_ == NULL) + goto restart; + + add_history(command.c_str()); + + std::ostringstream str; + driver.source_->Show(str); + + std::string code(str.str()); + std::cout << code << std::endl; + + _pooled + + JSStringRef script(JSStringCreateWithUTF8CString(code.c_str())); + + JSContextRef context(CYGetJSContext()); + + JSValueRef exception(NULL); + JSValueRef result(JSEvaluateScript(context, script, NULL, NULL, 0, &exception)); + JSStringRelease(script); + + if (exception != NULL) + result = exception; + + if (JSValueIsUndefined(context, result)) + goto restart; + + CFStringRef json; + + @try { json: + json = CYCopyJSONString(context, result); + } @catch (id error) { + CYThrow(context, error, &result); + goto json; + } + + fputs([reinterpret_cast(json) UTF8String], fout); + CFRelease(json); -int CYConsole(FILE *in, FILE *out, FILE *err); + fputs("\n", fout); + fflush(fout); + } -@ /**/protocol a -- (void) a:(int)m; -@end + fputs("\n", fout); + fflush(fout); -int main() { - return CYConsole(stdin, stdout, stderr); + return 0; } diff --git a/Library.mm b/Library.mm index 2dc719e..b6b2f71 100644 --- a/Library.mm +++ b/Library.mm @@ -40,12 +40,13 @@ #define _GNU_SOURCE #include -#include "Struct.hpp" +#include "cycript.h" #include "sig/parse.hpp" #include "sig/ffi_type.hpp" #include "Pooling.hpp" +#include "Struct.hpp" #include @@ -53,14 +54,6 @@ #include #include -#include - -#include -#include -#include -#include -#include -#include #include @@ -72,7 +65,6 @@ #include #include #include -#include #include "Parser.hpp" #include "Cycript.tab.hh" @@ -90,8 +82,6 @@ } while (false) -#define _pooled _H _pool([[NSAutoreleasePool alloc] init], true); - static JSContextRef Context_; static JSClassRef Functor_; @@ -271,7 +261,7 @@ JSObjectRef CYMakeObject(JSContextRef context, id object) { @end -JSContextRef JSGetContext() { +extern "C" JSContextRef CYGetJSContext() { return Context_; } @@ -404,7 +394,7 @@ JSValueRef CYCastJSValue(JSContextRef context, id value) { return value == nil ? JSValueMakeNull(context) : [value cy$JSValueInContext:context]; } -void CYThrow(JSContextRef context, id error, JSValueRef *exception) { +extern "C" void CYThrowNSError(JSContextRef context, id error, JSValueRef *exception) { *exception = CYCastJSValue(context, error); } @@ -479,7 +469,7 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { @end -CFStringRef JSValueToJSONCopy(JSContextRef context, JSValueRef value) { +extern "C" CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value) { id object(CYCastNSObject(context, value)); return reinterpret_cast([(object == nil ? @"null" : [object cy$toJSON]) retain]); } @@ -507,13 +497,13 @@ static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef addr JSStringRef script(JSStringCreateWithCFString(code)); CFRelease(code); - JSValueRef result(JSEvaluateScript(JSGetContext(), script, NULL, NULL, 0, NULL)); + JSValueRef result(JSEvaluateScript(CYGetJSContext(), script, NULL, NULL, 0, NULL)); JSStringRelease(script); CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1)); CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8")); - CFStringRef json(JSValueToJSONCopy(JSGetContext(), result)); + CFStringRef json(CYCopyJSONString(CYGetJSContext(), result)); CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL)); CFRelease(json); @@ -841,7 +831,7 @@ static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, J if (NSMutableArray *entry = [Bridge_ objectForKey:name]) switch ([[entry objectAtIndex:0] intValue]) { case 0: - return JSEvaluateScript(JSGetContext(), CYJSString([entry objectAtIndex:1]), NULL, NULL, 0, NULL); + return JSEvaluateScript(CYGetJSContext(), CYJSString([entry objectAtIndex:1]), NULL, NULL, 0, NULL); case 1: return CYMakeFunction(context, [name cy$symbol], [[entry objectAtIndex:1] UTF8String]); case 2: @@ -938,93 +928,6 @@ void cy::parser::error(const cy::parser::location_type &location, const std::str driver.errors_.push_back(error); } -void CYConsole(FILE *fin, FILE *fout, FILE *ferr) { - std::string line; - - __gnu_cxx::stdio_filebuf bin(fin, std::ios::in); - std::istream sin(&bin); - - restart: while (!feof(fin)) { _pooled - fputs("cy# ", fout); - fflush(fout); - - std::string command; - std::vector lines; - - read: - if (!std::getline(sin, line)) - break; - - lines.push_back(line); - command += line; - - CYDriver driver(""); - cy::parser parser(driver); - - driver.data_ = command.c_str(); - driver.size_ = command.size(); - - if (parser.parse() != 0) { - for (CYDriver::Errors::const_iterator i(driver.errors_.begin()); i != driver.errors_.end(); ++i) { - cy::position begin(i->location_.begin); - if (begin.line != lines.size() || begin.column - 1 != lines.back().size()) { - std::cerr << i->message_ << std::endl; - goto restart; - } - } - - driver.errors_.clear(); - - fputs("cy> ", fout); - fflush(fout); - - command += '\n'; - goto read; - } - - if (driver.source_ == NULL) - goto restart; - - std::ostringstream str; - driver.source_->Show(str); - - std::string code(str.str()); - std::cout << code << std::endl; - - JSStringRef script(JSStringCreateWithUTF8CString(code.c_str())); - - JSContextRef context(JSGetContext()); - - JSValueRef exception(NULL); - JSValueRef result(JSEvaluateScript(context, script, NULL, NULL, 0, &exception)); - JSStringRelease(script); - - if (exception != NULL) - result = exception; - - if (JSValueIsUndefined(context, result)) - goto restart; - - CFStringRef json; - - @try { json: - json = JSValueToJSONCopy(context, result); - } @catch (id error) { - CYThrow(context, error, &result); - goto json; - } - - fputs([reinterpret_cast(json) UTF8String], fout); - CFRelease(json); - - fputs("\n", fout); - fflush(fout); - } - - fputs("\n", fout); - fflush(fout); -} - MSInitialize { _pooled apr_initialize(); @@ -1095,8 +998,8 @@ MSInitialize { _pooled length_ = JSStringCreateWithUTF8CString("length"); JSValueRef exception(NULL); - JSValueRef value(JSObjectGetProperty(JSGetContext(), global, CYJSString("Array"), &exception)); + JSValueRef value(JSObjectGetProperty(CYGetJSContext(), global, CYJSString("Array"), &exception)); CYThrow(context, exception); - Array_ = JSValueToObject(JSGetContext(), value, &exception); + Array_ = JSValueToObject(CYGetJSContext(), value, &exception); CYThrow(context, exception); } diff --git a/cycript.h b/cycript.h new file mode 100644 index 0000000..482d3f7 --- /dev/null +++ b/cycript.h @@ -0,0 +1,36 @@ +#ifndef CYCRIPT_H +#define CYCRIPT_H + +#ifdef __OBJC__ +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +JSContextRef CYGetJSContext(); +CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value); + +#ifdef __OBJC__ +void CYThrowNSError(JSContextRef context, id error, JSValueRef *exception); +#endif + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus +inline void CYThrow(JSContextRef context, id error, JSValueRef *exception) { + return CYThrowNSError(context, error, exception); +} +#endif + +#endif/*CYCRIPT_H*/ diff --git a/makefile b/makefile index d8533de..791a071 100644 --- a/makefile +++ b/makefile @@ -6,7 +6,8 @@ endif package: -flags := -mthumb -g3 -O0 -Wall -Werror -I. +flags := -mthumb -g3 -O0 -Wall -Werror -I. -fno-common +flags += -F${PKG_ROOT}/System/Library/PrivateFrameworks all: cycript libcycript.dylib libcycript.plist @@ -49,15 +50,18 @@ lex.cy.o: lex.cy.c Cycript.tab.hh Parser.hpp Pooling.hpp Output.o: Output.cpp Parser.hpp Pooling.hpp $(target)g++ $(flags) -c -o $@ $< -Library.o: Library.mm Cycript.tab.hh Parser.hpp Pooling.hpp Struct.hpp +Library.o: Library.mm Cycript.tab.hh Parser.hpp Pooling.hpp Struct.hpp cycript.h + $(target)g++ $(flags) -c -o $@ $< + +Application.o: Application.mm Cycript.tab.hh Parser.hpp Pooling.hpp cycript.h $(target)g++ $(flags) -c -o $@ $< libcycript.dylib: ffi_type.o parse.o Output.o Cycript.tab.o lex.cy.o Library.o - $(target)g++ $(flags) -dynamiclib -o $@ $(filter %.o,$^) -lobjc -framework CFNetwork -framework JavaScriptCore -framework WebCore -install_name /usr/lib/libcycript.dylib -framework CoreFoundation -framework Foundation -F${PKG_ROOT}/System/Library/PrivateFrameworks -L$(menes)/mobilesubstrate -lsubstrate -lapr-1 -lffi + $(target)g++ $(flags) -dynamiclib -o $@ $(filter %.o,$^) -lobjc -framework CFNetwork -framework JavaScriptCore -framework WebCore -install_name /usr/lib/libcycript.dylib -framework CoreFoundation -framework Foundation -L$(menes)/mobilesubstrate -lsubstrate -lapr-1 -lffi ldid -S $@ -cycript: Application.mm libcycript.dylib - $(target)g++ $(flags) -o $@ $(filter %.mm,$^) -framework UIKit -framework Foundation -framework CoreFoundation -lobjc libcycript.dylib +cycript: Application.o libcycript.dylib + $(target)g++ $(flags) -o $@ $(filter %.o,$^) -framework UIKit -framework Foundation -framework CoreFoundation -lobjc libcycript.dylib -lreadline -framework JavaScriptCore ldid -S cycript package: all -- 2.45.2