From: Jay Freeman (saurik) Date: Thu, 8 Oct 2009 20:38:21 +0000 (+0000) Subject: Drastic modifications to exception handling that required temporarily bringing back... X-Git-Tag: v0.9.432~375 X-Git-Url: https://git.saurik.com/cycript.git/commitdiff_plain/4cf49641600bf5204fce42b168b489ea19fc865a Drastic modifications to exception handling that required temporarily bringing back Objective- for the core Application :(. --- diff --git a/Application.cpp b/Application.cpp deleted file mode 100644 index ae638a6..0000000 --- a/Application.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#define _GNU_SOURCE - -#include -#include "cycript.hpp" - -#include -#include - -#include - -#include -#include - -#include - -#include -#include - -#include -#include -#include - -#include "Cycript.tab.hh" - -static jmp_buf ctrlc_; - -void sigint(int) { - longjmp(ctrlc_, 1); -} - -void Run(const char *code, FILE *fout) { - JSStringRef script(JSStringCreateWithUTF8CString(code)); - - 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)) { - CYPool pool; - const char *json; - - json = CYPoolJSONString(pool, context, result); - - if (fout != NULL) { - fputs(json, fout); - fputs("\n", fout); - fflush(fout); - } - } -} - -void Console() { - bool bypass(false); - bool debug(false); - - 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; - - bool extra(false); - const char *prompt("cy# "); - - if (setjmp(ctrlc_) != 0) { - fputs("\n", fout); - fflush(fout); - goto restart; - } - - read: - char *line(readline(prompt)); - if (line == NULL) - break; - - if (!extra) { - extra = true; - if (line[0] == '\\') { - std::string data(line + 1); - if (data == "bypass") { - bypass = !bypass; - fprintf(fout, "bypass == %s\n", bypass ? "true" : "false"); - fflush(fout); - } else if (data == "debug") { - debug = !debug; - fprintf(fout, "debug == %s\n", debug ? "true" : "false"); - fflush(fout); - } - add_history(line); - goto restart; - } - } - - lines.push_back(line); - command += line; - free(line); - - std::string code; - - if (bypass) - code = command; - else { - CYDriver driver(""); - cy::parser parser(driver); - - driver.data_ = command.c_str(); - driver.size_ = command.size(); - - if (parser.parse() != 0 || !driver.errors_.empty()) { - 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; - add_history(command.c_str()); - goto restart; - } - } - - driver.errors_.clear(); - - command += '\n'; - prompt = "cy> "; - goto read; - } - - if (driver.source_ == NULL) - goto restart; - - std::ostringstream str; - driver.source_->Show(str); - code = str.str(); - } - - add_history(command.c_str()); - - if (debug) - std::cout << code << std::endl; - - Run(code.c_str(), fout); - } - - fputs("\n", fout); - fflush(fout); -} - -void *Map(const char *path, size_t *psize) { - int fd; - _syscall(fd = open(path, O_RDONLY)); - - struct stat stat; - _syscall(fstat(fd, &stat)); - size_t size(stat.st_size); - - *psize = size; - - void *base; - _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); - - _syscall(close(fd)); - return base; -} - -int main(int argc, const char *argv[]) { - const char *script; - - if (argc == 1) - script = NULL; - else { - CYSetArgs(argc - 1, argv + 1); - script = argv[1]; - } - - if (script == NULL || strcmp(script, "-") == 0) - Console(); - else { - CYDriver driver(script); - cy::parser parser(driver); - - size_t size; - char *start(reinterpret_cast(Map(script, &size))); - char *end(start + size); - - if (size >= 2 && start[0] == '#' && start[1] == '!') { - start += 2; - while (start != end && *start++ != '\n'); - } - - driver.data_ = start; - driver.size_ = end - start; - - if (parser.parse() != 0 || !driver.errors_.empty()) { - 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.source_ != NULL) { - std::ostringstream str; - driver.source_->Show(str); - std::string code(str.str()); - std::cout << code << std::endl; - Run(code.c_str(), stdout); - } - } - - return 0; -} diff --git a/Application.mm b/Application.mm new file mode 100644 index 0000000..31b7a45 --- /dev/null +++ b/Application.mm @@ -0,0 +1,221 @@ +#define _GNU_SOURCE + +#include +#include "cycript.hpp" + +#include +#include + +#include + +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include "Cycript.tab.hh" + +static jmp_buf ctrlc_; + +void sigint(int) { + longjmp(ctrlc_, 1); +} + +void Run(const char *code, FILE *fout) { _pooled + JSStringRef script(JSStringCreateWithUTF8CString(code)); + + JSContextRef context(CYGetJSContext()); + + JSValueRef exception(NULL); + JSValueRef result(JSEvaluateScript(context, script, NULL, NULL, 0, &exception)); + JSStringRelease(script); + + if (exception != NULL) { error: + result = exception; + exception = NULL; + } + + if (!JSValueIsUndefined(context, result)) { + CYPool pool; + const char *json; + + json = CYPoolJSONString(pool, context, result, &exception); + if (exception != NULL) + goto error; + + if (fout != NULL) { + fputs(json, fout); + fputs("\n", fout); + fflush(fout); + } + } +} + +void Console() { + bool bypass(false); + bool debug(false); + + 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; + + bool extra(false); + const char *prompt("cy# "); + + if (setjmp(ctrlc_) != 0) { + fputs("\n", fout); + fflush(fout); + goto restart; + } + + read: + char *line(readline(prompt)); + if (line == NULL) + break; + + if (!extra) { + extra = true; + if (line[0] == '\\') { + std::string data(line + 1); + if (data == "bypass") { + bypass = !bypass; + fprintf(fout, "bypass == %s\n", bypass ? "true" : "false"); + fflush(fout); + } else if (data == "debug") { + debug = !debug; + fprintf(fout, "debug == %s\n", debug ? "true" : "false"); + fflush(fout); + } + add_history(line); + goto restart; + } + } + + lines.push_back(line); + command += line; + free(line); + + std::string code; + + if (bypass) + code = command; + else { + CYDriver driver(""); + cy::parser parser(driver); + + driver.data_ = command.c_str(); + driver.size_ = command.size(); + + if (parser.parse() != 0 || !driver.errors_.empty()) { + 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; + add_history(command.c_str()); + goto restart; + } + } + + driver.errors_.clear(); + + command += '\n'; + prompt = "cy> "; + goto read; + } + + if (driver.source_ == NULL) + goto restart; + + std::ostringstream str; + driver.source_->Show(str); + code = str.str(); + } + + add_history(command.c_str()); + + if (debug) + std::cout << code << std::endl; + + Run(code.c_str(), fout); + } + + fputs("\n", fout); + fflush(fout); +} + +void *Map(const char *path, size_t *psize) { + int fd; + _syscall(fd = open(path, O_RDONLY)); + + struct stat stat; + _syscall(fstat(fd, &stat)); + size_t size(stat.st_size); + + *psize = size; + + void *base; + _syscall(base = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0)); + + _syscall(close(fd)); + return base; +} + +int main(int argc, const char *argv[]) { + const char *script; + + if (argc == 1) + script = NULL; + else { + CYSetArgs(argc - 1, argv + 1); + script = argv[1]; + } + + if (script == NULL || strcmp(script, "-") == 0) + Console(); + else { + CYDriver driver(script); + cy::parser parser(driver); + + size_t size; + char *start(reinterpret_cast(Map(script, &size))); + char *end(start + size); + + if (size >= 2 && start[0] == '#' && start[1] == '!') { + start += 2; + while (start != end && *start++ != '\n'); + } + + driver.data_ = start; + driver.size_ = end - start; + + if (parser.parse() != 0 || !driver.errors_.empty()) { + 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.source_ != NULL) { + std::ostringstream str; + driver.source_->Show(str); + std::string code(str.str()); + std::cout << code << std::endl; + Run(code.c_str(), stdout); + } + } + + return 0; +} diff --git a/Library.mm b/Library.mm index 4213e5b..cc57c44 100644 --- a/Library.mm +++ b/Library.mm @@ -82,6 +82,22 @@ CFLog(kCFLogLevelNotice, CFSTR("_trace():%u"), __LINE__); \ } while (false) +#define CYPoolTry { \ + id _saved(nil); \ + NSAutoreleasePool *_pool([[NSAutoreleasePool alloc] init]); \ + @try +#define CYPoolCatch(value) \ + @catch (NSException *error) { \ + _saved = [error retain]; \ + @throw; \ + return value; \ + } @finally { \ + [_pool release]; \ + if (_saved != nil) \ + [_saved autorelease]; \ + } \ +} + static JSGlobalContextRef Context_; static JSObjectRef System_; @@ -179,7 +195,7 @@ struct jocData : ptrData { } }; -JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient = true) { +JSObjectRef CYMakeInstance(JSContextRef context, id object, bool transient) { if (!transient) object = [object retain]; jocData *data(new jocData(object, transient)); @@ -229,7 +245,7 @@ JSValueRef CYJSUndefined(JSContextRef context) { @interface NSObject (Cycript) - (bool) cy$isUndefined; - (NSString *) cy$toJSON; -- (JSValueRef) cy$JSValueInContext:(JSContextRef)context; +- (JSValueRef) cy$JSValueInContext:(JSContextRef)context transient:(bool)transient; @end @interface NSString (Cycript) @@ -250,8 +266,8 @@ JSValueRef CYJSUndefined(JSContextRef context) { return [self description]; } -- (JSValueRef) cy$JSValueInContext:(JSContextRef)context { - return CYMakeInstance(context, self); +- (JSValueRef) cy$JSValueInContext:(JSContextRef)context transient:(bool)transient { + return CYMakeInstance(context, self, transient); } @end @@ -266,7 +282,7 @@ JSValueRef CYJSUndefined(JSContextRef context) { return @"undefined"; } -- (JSValueRef) cy$JSValueInContext:(JSContextRef)context { +- (JSValueRef) cy$JSValueInContext:(JSContextRef)context transient:(bool)transient { return CYJSUndefined(context); } @@ -336,7 +352,7 @@ JSValueRef CYJSUndefined(JSContextRef context) { return [self class] != NSCFBoolean_ ? [self stringValue] : [self boolValue] ? @"true" : @"false"; } -- (JSValueRef) cy$JSValueInContext:(JSContextRef)context { +- (JSValueRef) cy$JSValueInContext:(JSContextRef)context transient:(bool)transient { return [self class] != NSCFBoolean_ ? CYCastJSValue(context, [self doubleValue]) : CYCastJSValue(context, [self boolValue]); } @@ -404,6 +420,8 @@ JSGlobalContextRef CYGetJSContext() { return Context_; } +#define CYTry \ + @try #define CYCatch \ @catch (id error) { \ NSLog(@"e:%@", error); \ @@ -623,8 +641,8 @@ JSValueRef CYCastJSValue(JSContextRef context, const char *value) { return CYCastJSValue(context, CYJSString(value)); } -JSValueRef CYCastJSValue(JSContextRef context, id value) { - return value == nil ? CYJSNull(context) : [value cy$JSValueInContext:context]; +JSValueRef CYCastJSValue(JSContextRef context, id value, bool transient = true) { + return value == nil ? CYJSNull(context) : [value cy$JSValueInContext:context transient:transient]; } JSObjectRef CYCastJSObject(JSContextRef context, JSValueRef value) { @@ -648,6 +666,8 @@ void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, J } void CYThrow(JSContextRef context, id error, JSValueRef *exception) { + if (exception == NULL) + throw error; *exception = CYCastJSValue(context, error); } @@ -713,16 +733,21 @@ void CYThrow(JSContextRef context, id error, JSValueRef *exception) { @end -CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value) { _pooled - id object(CYCastNSObject(NULL, context, value)); - return reinterpret_cast([(object == nil ? @"null" : [object cy$toJSON]) retain]); +CFStringRef CYCopyJSONString(JSContextRef context, JSValueRef value, JSValueRef *exception) { + CYTry { + CYPoolTry { + id object(CYCastNSObject(NULL, context, value)); + return reinterpret_cast([(object == nil ? @"null" : [object cy$toJSON]) retain]); + } CYPoolCatch(NULL) + } CYCatch } -const char *CYPoolJSONString(apr_pool_t *pool, JSContextRef context, JSValueRef value) { - NSString *json((NSString *) CYCopyJSONString(context, value)); - const char *string(CYPoolCString(pool, json)); - [json release]; - return string; +const char *CYPoolJSONString(apr_pool_t *pool, JSContextRef context, JSValueRef value, JSValueRef *exception) { + if (NSString *json = (NSString *) CYCopyJSONString(context, value, exception)) { + const char *string(CYPoolCString(pool, json)); + [json release]; + return string; + } else return NULL; } static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *value, void *info) { @@ -754,7 +779,7 @@ static void OnData(CFSocketRef socket, CFSocketCallBackType type, CFDataRef addr CFHTTPMessageRef response(CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1)); CFHTTPMessageSetHeaderFieldValue(response, CFSTR("Content-Type"), CFSTR("application/json; charset=utf-8")); - CFStringRef json(CYCopyJSONString(CYGetJSContext(), result)); + CFStringRef json(CYCopyJSONString(CYGetJSContext(), result, NULL)); CFDataRef body(CFStringCreateExternalRepresentation(kCFAllocatorDefault, json, kCFStringEncodingUTF8, NULL)); CFRelease(json); @@ -799,7 +824,7 @@ static void OnAccept(CFSocketRef socket, CFSocketCallBackType type, CFDataRef ad } static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { - @try { + CYTry { CYPool pool; NSString *name(CYCastNSString(pool, property)); NSLog(@"get:%@", name); @@ -808,7 +833,7 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object, } static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef value, JSValueRef *exception) { - @try { + CYTry { CYPool pool; NSString *name(CYCastNSString(pool, property)); NSLog(@"set:%@", name); @@ -817,7 +842,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr } static bool Instance_deleteProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { - @try { + CYTry { CYPool pool; NSString *name(CYCastNSString(pool, property)); NSLog(@"delete:%@", name); @@ -826,9 +851,9 @@ static bool Instance_deleteProperty(JSContextRef context, JSObjectRef object, JS } static JSObjectRef Instance_callAsConstructor(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - @try { + CYTry { jocData *data(reinterpret_cast(JSObjectGetPrivate(object))); - return CYMakeInstance(context, [data->GetValue() alloc]); + return CYMakeInstance(context, [data->GetValue() alloc], true); } CYCatch } @@ -1000,7 +1025,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { break; case sig::typename_P: - value = CYMakeInstance(context, *reinterpret_cast(data)); + value = CYMakeInstance(context, *reinterpret_cast(data), true); break; case sig::selector_P: @@ -1041,7 +1066,7 @@ JSValueRef CYFromFFI(JSContextRef context, sig::Type *type, void *data) { } static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSValueRef *arguments, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)()) { - @try { + CYTry { if (count != signature->count - 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to ffi function" userInfo:nil]; @@ -1063,7 +1088,6 @@ static JSValueRef CYCallFunction(JSContextRef context, size_t count, const JSVal } void Closure_(ffi_cif *cif, void *result, void **arguments, void *arg) { - NSLog(@"Closure()"); ffoData *data(reinterpret_cast(arg)); JSContextRef context(data->context_); @@ -1106,11 +1130,11 @@ JSObjectRef CYMakeFunctor(JSContextRef context, JSObjectRef function, const char } static JSValueRef Global_getProperty(JSContextRef context, JSObjectRef object, JSStringRef property, JSValueRef *exception) { - @try { + CYTry { CYPool pool; NSString *name(CYCastNSString(pool, property)); if (Class _class = NSClassFromString(name)) - return CYMakeInstance(context, _class); + return CYMakeInstance(context, _class, true); if (NSMutableArray *entry = [Bridge_ objectForKey:name]) switch ([[entry objectAtIndex:0] intValue]) { case 0: @@ -1140,14 +1164,14 @@ extern "C" { } static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - @try { + CYTry { NSLog(@"%s", CYCastCString(context, arguments[0])); return CYJSUndefined(context); } CYCatch } static JSValueRef CYApplicationMain(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - @try { + CYTry { CYPool pool; NSString *name(CYCastNSObject(pool, context, arguments[0])); int argc(*_NSGetArgc()); @@ -1164,7 +1188,7 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje CYPool pool; - @try { + CYTry { if (count < 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"too few arguments to objc_msgSend" userInfo:nil]; @@ -1177,11 +1201,13 @@ static JSValueRef $objc_msgSend(JSContextRef context, JSObjectRef object, JSObje Class _class(object_getClass(self)); if (Method method = class_getInstanceMethod(_class, _cmd)) type = method_getTypeEncoding(method); - else { _pooled - NSMethodSignature *method([self methodSignatureForSelector:_cmd]); - if (method == nil) - @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self] userInfo:nil]; - type = CYPoolCString(pool, [method _typeString]); + else { + CYPoolTry { + NSMethodSignature *method([self methodSignatureForSelector:_cmd]); + if (method == nil) + @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"unrecognized selector %s sent to object %p", sel_getName(_cmd), self] userInfo:nil]; + type = CYPoolCString(pool, [method _typeString]); + } CYPoolCatch(NULL) } } CYCatch @@ -1209,7 +1235,7 @@ static JSValueRef Functor_callAsFunction(JSContextRef context, JSObjectRef objec } JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - @try { + CYTry { if (count != 1) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector constructor" userInfo:nil]; const char *name(CYCastCString(context, arguments[0])); @@ -1218,7 +1244,7 @@ JSObjectRef Selector_new(JSContextRef context, JSObjectRef object, size_t count, } JSObjectRef Functor_new(JSContextRef context, JSObjectRef object, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - @try { + CYTry { if (count != 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Functor constructor" userInfo:nil]; const char *type(CYCastCString(context, arguments[1])); @@ -1244,22 +1270,25 @@ JSValueRef Selector_getProperty_prototype(JSContextRef context, JSObjectRef obje return Function_; } -static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { _pooled - @try { +static JSValueRef Instance_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { + CYTry { jocData *data(reinterpret_cast(JSObjectGetPrivate(_this))); - return CYCastJSValue(context, CYJSString([data->GetValue() description])); + NSString *description; CYPoolTry { + description = [data->GetValue() description]; + } CYPoolCatch(NULL) + return CYCastJSValue(context, CYJSString(description)); } CYCatch } static JSValueRef Selector_callAsFunction_toString(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - @try { + CYTry { selData *data(reinterpret_cast(JSObjectGetPrivate(_this))); return CYCastJSValue(context, sel_getName(data->GetValue())); } CYCatch } static JSValueRef Selector_callAsFunction_type(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) { - @try { + CYTry { if (count != 2) @throw [NSException exceptionWithName:NSInvalidArgumentException reason:@"incorrect number of arguments to Selector.type" userInfo:nil]; CYPool pool; diff --git a/cycript.hpp b/cycript.hpp index 1096ac1..b73d5c6 100644 --- a/cycript.hpp +++ b/cycript.hpp @@ -11,7 +11,7 @@ #include JSGlobalContextRef CYGetJSContext(); -const char *CYPoolJSONString(apr_pool_t *pool, JSContextRef context, JSValueRef value); +const char *CYPoolJSONString(apr_pool_t *pool, JSContextRef context, JSValueRef value, JSValueRef *exception); void CYSetArgs(int argc, const char *argv[]); #endif/*CYCRIPT_HPP*/ diff --git a/makefile b/makefile index c893967..607adef 100644 --- a/makefile +++ b/makefile @@ -56,7 +56,7 @@ Output.o: Output.cpp Parser.hpp Pooling.hpp Library.o: Library.mm Cycript.tab.hh Parser.hpp Pooling.hpp Struct.hpp cycript.hpp $(target)g++ $(flags) -c -o $@ $< -Application.o: Application.cpp Cycript.tab.hh Parser.hpp Pooling.hpp cycript.hpp +Application.o: Application.mm Cycript.tab.hh Parser.hpp Pooling.hpp cycript.hpp $(target)g++ $(flags) -c -o $@ $< libcycript.dylib: ffi_type.o parse.o Output.o Cycript.tab.o lex.cy.o Library.o