]> git.saurik.com Git - cycript.git/blobdiff - Library.mm
Forgot the new .mk files in previous commit.
[cycript.git] / Library.mm
index 1b4a19820ed6fcda6ed2ba39a157242a3d0d6d16..b05138a498bff1a32ecede8c499bfdda74868e63 100644 (file)
@@ -37,8 +37,6 @@
 */
 /* }}} */
 
-#define _GNU_SOURCE
-
 #include <substrate.h>
 #include "cycript.hpp"
 
 #include "Pooling.hpp"
 #include "Struct.hpp"
 
+#ifdef __APPLE__
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreFoundation/CFLogUtilities.h>
+#include <JavaScriptCore/JSStringRefCF.h>
+#endif
+
+#include <Foundation/Foundation.h>
 
 #include <WebKit/WebScriptObject.h>
 
@@ -66,7 +69,7 @@
 #include "Parser.hpp"
 #include "Cycript.tab.hh"
 
-#include <apr-1/apr_thread_proc.h>
+#include <apr_thread_proc.h>
 
 #undef _assert
 #undef _trace
 
 void CYThrow(JSContextRef context, JSValueRef value);
 
+const char *CYPoolCCYON(apr_pool_t *pool, JSContextRef context, JSValueRef value, JSValueRef *exception);
+JSStringRef CYCopyJSString(const char *value);
+
+void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, JSValueRef value);
+
+JSValueRef CYCallFunction(apr_pool_t *pool, JSContextRef context, size_t setups, void *setup[], size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception, sig::Signature *signature, ffi_cif *cif, void (*function)());
+JSValueRef CYSendMessage(apr_pool_t *pool, JSContextRef context, id self, SEL _cmd, size_t count, const JSValueRef arguments[], bool initialize, JSValueRef *exception);
+
 /* JavaScript Properties {{{ */
 JSValueRef CYGetProperty(JSContextRef context, JSObjectRef object, size_t index) {
     JSValueRef exception(NULL);
@@ -126,11 +137,6 @@ void CYSetProperty(JSContextRef context, JSObjectRef object, JSStringRef name, J
 }
 /* }}} */
 /* JavaScript Strings {{{ */
-JSStringRef CYCopyJSString(id value) {
-    // XXX: this definition scares me; is anyone using this?!
-    return value == NULL ? NULL : JSStringCreateWithCFString(reinterpret_cast<CFStringRef>([value description]));
-}
-
 JSStringRef CYCopyJSString(const char *value) {
     return value == NULL ? NULL : JSStringCreateWithUTF8CString(value);
 }
@@ -194,7 +200,25 @@ class CYJSString {
         return string_;
     }
 };
+/* }}} */
+/* Objective-C Strings {{{ */
+JSStringRef CYCopyJSString_(NSString *value) {
+#ifdef __APPLE__
+    return JSStringCreateWithCFString(reinterpret_cast<CFStringRef>(string));
+#else
+    return CYCopyJSString([value UTF8String]);
+#endif
+}
+
+JSStringRef CYCopyJSString(id value) {
+    if (value == nil)
+        return NULL;
+    // XXX: this definition scares me; is anyone using this?!
+    NSString *string([value description]);
+    return CYCopyJSString_(string);
+}
 
+#ifdef __APPLE__
 CFStringRef CYCopyCFString(JSStringRef value) {
     return JSStringCopyCFString(kCFAllocatorDefault, value);
 }
@@ -202,7 +226,7 @@ CFStringRef CYCopyCFString(JSStringRef value) {
 CFStringRef CYCopyCFString(JSContextRef context, JSValueRef value) {
     return CYCopyCFString(CYJSString(context, value));
 }
-
+#endif
 /* }}} */
 
 static JSGlobalContextRef Context_;
@@ -219,7 +243,6 @@ static JSClassRef Pointer_;
 static JSClassRef Runtime_;
 static JSClassRef Selector_;
 static JSClassRef Struct_;
-static JSClassRef Type_;
 
 static JSClassRef ObjectiveC_Classes_;
 static JSClassRef ObjectiveC_Image_Classes_;
@@ -271,8 +294,8 @@ struct CYValue :
     CYValue() {
     }
 
-    CYValue(void *value) :
-        value_(value)
+    CYValue(const void *value) :
+        value_(const_cast<void *>(value))
     {
     }
 
@@ -307,7 +330,7 @@ JSValueRef CYGetClassPrototype(JSContextRef context, id self) {
         return Instance_prototype_;
 
     // XXX: I need to think through multi-context
-    typedef std::map<Class, JSValueRef> CacheMap;
+    typedef std::map<id, JSValueRef> CacheMap;
     static CacheMap cache_;
 
     JSValueRef &value(cache_[self]);
@@ -352,6 +375,7 @@ struct Instance :
     virtual ~Instance() {
         if ((flags_ & Transient) == 0)
             // XXX: does this handle background threads correctly?
+            // XXX: this simply does not work on the console because I'm stupid
             [GetValue() performSelector:@selector(release) withObject:nil afterDelay:0];
     }
 
@@ -469,9 +493,14 @@ void Copy(apr_pool_t *pool, Type &lhs, Type &rhs) {
     if (sig::IsAggregate(rhs.primitive))
         Copy(pool, lhs.data.signature, rhs.data.signature);
     else {
-        if (rhs.data.data.type != NULL) {
-            lhs.data.data.type = new(pool) Type;
-            Copy(pool, *lhs.data.data.type, *rhs.data.data.type);
+        sig::Type *&lht(lhs.data.data.type);
+        sig::Type *&rht(rhs.data.data.type);
+
+        if (rht == NULL)
+            lht = NULL;
+        else {
+            lht = new(pool) Type;
+            Copy(pool, *lht, *rht);
         }
 
         lhs.data.data.size = rhs.data.data.size;
@@ -537,6 +566,8 @@ struct Type_privateData :
     static Type_privateData *Object;
     static Type_privateData *Selector;
 
+    static JSClassRef Class;
+
     ffi_type *ffi_;
     sig::Type *type_;
 
@@ -815,6 +846,7 @@ NSString *CYPoolNSCYON(apr_pool_t *pool, id value);
 - (void *) cy$symbol;
 @end
 
+#ifdef __APPLE__
 struct PropertyAttributes {
     CYPool pool_;
 
@@ -900,10 +932,13 @@ struct PropertyAttributes {
     }
 
 };
+#endif
 
+#ifdef __APPLE__
 NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) {
     return [(NSString *) CFCopyDescription((CFTypeRef) self) autorelease];
 }
+#endif
 
 /* Bridge: NSArray {{{ */
 @implementation NSArray (Cycript)
@@ -913,7 +948,13 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) {
     [json appendString:@"["];
 
     bool comma(false);
+#ifdef __APPLE__
     for (id object in self) {
+#else
+    id object;
+    for (size_t index(0), count([self count]); index != count; ++index) {
+        object = [self objectAtIndex:index];
+#endif
         if (comma)
             [json appendString:@","];
         else
@@ -942,8 +983,14 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) {
 }
 
 - (NSObject *) cy$getProperty:(NSString *)name {
-    if ([name isEqualToString:@"length"])
-        return [NSNumber numberWithUnsignedInteger:[self count]];
+    if ([name isEqualToString:@"length"]) {
+        NSUInteger count([self count]);
+#ifdef __APPLE__
+        return [NSNumber numberWithUnsignedInteger:count];
+#else
+        return [NSNumber numberWithUnsignedInt:count];
+#endif
+    }
 
     size_t index(CYGetIndex(NULL, name));
     if (index == _not(size_t) || index >= [self count])
@@ -962,7 +1009,12 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) {
     [json appendString:@"{"];
 
     bool comma(false);
+#ifdef __APPLE__
     for (id key in self) {
+#else
+    NSEnumerator *keys([self keyEnumerator]);
+    while (id key = [keys nextObject]) {
+#endif
         if (comma)
             [json appendString:@","];
         else
@@ -993,7 +1045,12 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) {
 - (bool) cy$setProperty:(NSString *)name to:(NSObject *)value {
     if ([name isEqualToString:@"length"]) {
         // XXX: is this not intelligent?
-        NSUInteger size([(NSNumber *)value unsignedIntegerValue]);
+        NSNumber *number(reinterpret_cast<NSNumber *>(value));
+#ifdef __APPLE__
+        NSUInteger size([number unsignedIntegerValue]);
+#else
+        NSUInteger size([number unsignedIntValue]);
+#endif
         NSUInteger count([self count]);
         if (size < count)
             [self removeObjectsInRange:NSMakeRange(size, count - size)];
@@ -1265,10 +1322,6 @@ NSString *NSCFType$cy$toJSON(id self, SEL sel, NSString *key) {
 
 @end
 
-CYRange DigitRange_    (0x3ff000000000000LLU, 0x000000000000000LLU); // 0-9
-CYRange WordStartRange_(0x000001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$
-CYRange WordEndRange_  (0x3ff001000000000LLU, 0x7fffffe87fffffeLLU); // A-Za-z_$0-9
-
 #define CYTry \
     @try
 #define CYCatch \
@@ -2227,11 +2280,13 @@ static JSValueRef Instance_getProperty(JSContextRef context, JSObjectRef object,
         const char *string(CYPoolCString(pool, name));
         Class _class(object_getClass(self));
 
+#ifdef __APPLE__
         if (objc_property_t property = class_getProperty(_class, string)) {
             PropertyAttributes attributes(property);
             SEL sel(sel_registerName(attributes.Getter()));
             return CYSendMessage(pool, context, self, sel, 0, NULL, false, exception);
         }
+#endif
 
         if (SEL sel = sel_getUid(string))
             if (CYImplements(self, _class, sel, true))
@@ -2259,6 +2314,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr
         const char *string(CYPoolCString(pool, name));
         Class _class(object_getClass(self));
 
+#ifdef __APPLE__
         if (objc_property_t property = class_getProperty(_class, string)) {
             PropertyAttributes attributes(property);
             if (const char *setter = attributes.Setter()) {
@@ -2268,6 +2324,7 @@ static bool Instance_setProperty(JSContextRef context, JSObjectRef object, JSStr
                 return true;
             }
         }
+#endif
 
         size_t length(strlen(string));
 
@@ -2800,12 +2857,14 @@ static bool stret(ffi_type *ffi_type) {
 extern "C" {
     int *_NSGetArgc(void);
     char ***_NSGetArgv(void);
-    int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
 }
 
 static JSValueRef System_print(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
     CYTry {
-        NSLog(@"%s", CYCastCString(context, arguments[0]));
+        if (count == 0)
+            NSLog(@"");
+        else
+            NSLog(@"%s", CYCastCString(context, arguments[0]));
         return CYJSUndefined(context);
     } CYCatch
 }
@@ -2914,6 +2973,11 @@ static JSValueRef objc_registerClassPair_(JSContextRef context, JSObjectRef obje
 }
 /* }}} */
 
+static JSValueRef Cycript_gc_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
+    JSGarbageCollect(context);
+    return CYJSUndefined(context);
+}
+
 static JSValueRef Selector_callAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef _this, size_t count, const JSValueRef arguments[], JSValueRef *exception) {
     JSValueRef setup[count + 2];
     setup[0] = _this;
@@ -3295,28 +3359,6 @@ static JSStaticFunction Type_staticFunctions[4] = {
     {NULL, NULL, 0}
 };
 
-CYDriver::CYDriver(const std::string &filename) :
-    state_(CYClear),
-    data_(NULL),
-    size_(0),
-    file_(NULL),
-    filename_(filename),
-    source_(NULL)
-{
-    ScannerInit();
-}
-
-CYDriver::~CYDriver() {
-    ScannerDestroy();
-}
-
-void cy::parser::error(const cy::parser::location_type &location, const std::string &message) {
-    CYDriver::Error error;
-    error.location_ = location;
-    error.message_ = message;
-    driver.errors_.push_back(error);
-}
-
 void CYSetArgs(int argc, const char *argv[]) {
     JSContextRef context(CYGetJSContext());
     JSValueRef args[argc];
@@ -3365,24 +3407,6 @@ const char *CYExecute(apr_pool_t *pool, const char *code) { _pooled
     return json;
 }
 
-bool CYRecvAll_(int socket, uint8_t *data, size_t size) {
-    while (size != 0) if (size_t writ = _syscall(recv(socket, data, size, 0))) {
-        data += writ;
-        size -= writ;
-    } else
-        return false;
-    return true;
-}
-
-bool CYSendAll_(int socket, const uint8_t *data, size_t size) {
-    while (size != 0) if (size_t writ = _syscall(send(socket, data, size, 0))) {
-        data += writ;
-        size -= writ;
-    } else
-        return false;
-    return true;
-}
-
 static apr_pool_t *Pool_;
 
 struct CYExecute_ {
@@ -3449,9 +3473,11 @@ struct CYClient :
                 json = NULL;
                 size = _not(size_t);
             } else {
+                CYContext context(driver.pool_);
+                driver.program_->Replace(context);
                 std::ostringstream str;
                 CYOutput out(str);
-                driver.source_->Show(out);
+                out << *driver.program_;
                 std::string code(str.str());
                 CYExecute_ execute = {pool, code.c_str()};
                 [client performSelectorOnMainThread:@selector(execute:) withObject:[NSValue valueWithPointer:&execute] waitUntilDone:YES];
@@ -3596,7 +3622,7 @@ JSGlobalContextRef CYGetJSContext() {
         definition.callAsFunction = &Type_callAsFunction;
         definition.callAsConstructor = &Type_callAsConstructor;
         definition.finalize = &Finalize;
-        Type_ = JSClassCreate(&definition);
+        Type_privateData::Class = JSClassCreate(&definition);
 
         definition = kJSClassDefinitionEmpty;
         definition.className = "Runtime";
@@ -3683,7 +3709,13 @@ JSGlobalContextRef CYGetJSContext() {
 
         MSHookFunction(&objc_registerClassPair, MSHake(objc_registerClassPair));
 
+#ifdef __APPLE__
         class_addMethod(NSCFType_, @selector(cy$toJSON:), reinterpret_cast<IMP>(&NSCFType$cy$toJSON), "@12@0:4@8");
+#endif
+
+        JSObjectRef cycript(JSObjectMake(context, NULL, NULL));
+        CYSetProperty(context, global, CYJSString("Cycript"), cycript);
+        CYSetProperty(context, cycript, CYJSString("gc"), JSObjectMakeFunctionWithCallback(context, CYJSString("gc"), &Cycript_gc_callAsFunction));
 
         CYSetProperty(context, global, CYJSString("objc_registerClassPair"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_registerClassPair"), &objc_registerClassPair_));
         CYSetProperty(context, global, CYJSString("objc_msgSend"), JSObjectMakeFunctionWithCallback(context, CYJSString("objc_msgSend"), &$objc_msgSend));