From ba4367141b7cdde7874984095aa299d29ff33cd8 Mon Sep 17 00:00:00 2001
From: Bill Welliver <bill@welliver.org>
Date: Sat, 5 Nov 2011 06:35:23 -0400
Subject: [PATCH] Updating the framework target and ObjectiveC interpreter
 class to be compatible with newer OSX releases.

---
 src/Makefile.in         |  10 ++--
 src/OCPikeInterpreter.h |   9 ++-
 src/OCPikeInterpreter.m | 130 ++++++++++++++++++++++++++--------------
 src/interpret.c         |   4 ++
 src/interpret.h         |   1 +
 src/version.c           |   2 +-
 src/version.h           |   2 +-
 7 files changed, 106 insertions(+), 52 deletions(-)

diff --git a/src/Makefile.in b/src/Makefile.in
index ace0f99970..6d96decf4f 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -294,11 +294,13 @@ compiler-warnings : clean
 # if you want to install the framework in a standard location, like /Library/Frameworks, you will
 # need to use install_name_tool to change the location. don't blame me, blame dyld.
 #
+# the following target assumes MacOS X 10.6 or higher, and is configured to use garbage collection
 framework: OCPikeInterpreter.o $(OBJ) modules/linker_options @STATIC_POST_MODULES_LINKOPTS@
 	@echo "Linking Pike.framework";\
-	gcc -o Pike OCPikeInterpreter.o $(OBJ) `cat modules/linker_options @STATIC_POST_MODULES_LINKOPTS@` -framework Cocoa -dynamiclib -Wl,-single_module \
-	  -undefined dynamic_lookup -mmacosx-version-min=10.4 -current_version 7.7 -install_name @executable_path/../Frameworks/Pike.framework/Pike \
-	  -isysroot /Developer/SDKs/MacOSX10.4u.sdk 
+	gcc -o Pike OCPikeInterpreter.o $(OBJ) `cat modules/linker_options @STATIC_POST_MODULES_LINKOPTS@` -framework Cocoa \ 
+	  -dynamiclib -Wl,-no_pie -mpic-no-dynamic -Wl,-single_module \
+	  -undefined dynamic_lookup -mmacosx-version-min=10.4 -current_version 7.9 -install_name @executable_path/../Frameworks/Pike.framework/Pike \
+	  -isysroot /Developer/SDKs/MacOSX10.6.sdk 
 	ls -l Pike
 	if test -x Pike.framework ; then rm -rf Pike.framework; fi
 	mkdir Pike.framework
@@ -525,7 +527,7 @@ undump_modules: delete_dumped_modules
 	@echo "Compiling `echo '$<' | sed -e 's|^$(PIKE_SRC_DIR)/||'`" ; \
 	rm -f $@.fail >/dev/null 2>&1; \
 	if test "x$@" = "xinterpret.o"; then EXTRAFLAGS="$(INTERPRET_DEOPTIMIZE)"; else EXTRAFLAGS=; fi; \
-	if $(CC) $(CFLAGS) $$EXTRAFLAGS -fobjc-exceptions -c $< -o $@ ; then : ; else \
+	if $(CC) $(CFLAGS) $$EXTRAFLAGS -fobjc-exceptions -fobjc-gc -c $< -o $@ ; then : ; else \
 	  status=$$?; \
 	  if test x"@noopt_retry@" = xyes ; then \
 	    echo "WARNING: Compiler failure! Trying without optimization!" >&2;\
diff --git a/src/OCPikeInterpreter.h b/src/OCPikeInterpreter.h
index 0d8e5aae19..2e31fdbd56 100644
--- a/src/OCPikeInterpreter.h
+++ b/src/OCPikeInterpreter.h
@@ -21,6 +21,7 @@
 #import <Foundation/NSObject.h>
 #import <Foundation/NSException.h>
 
+__attribute__((visibility("default")))
 @interface OCPikeInterpreter : NSObject
 {
   int is_started;
@@ -29,11 +30,17 @@
 }
 
 + (OCPikeInterpreter *)sharedInterpreter;
-- (id)init;
++ (id)allocWithZone:(NSZone *)zone;
+- (id)copyWithZone:(NSZone *)zone;
+- (id)retain;
+- (void)release;
+- (id)autorelease;
+- (NSUInteger)retainCount;
 - (void)setMaster:(id)master;
 - (BOOL)startInterpreter;
 - (BOOL)isStarted;
 - (BOOL)stopInterpreter;
+- (struct Pike_interpreter_struct *) getInterpreter;
 - (struct program *)compileString: (id)code;
 - (struct svalue *)evalString: (id)expression;
 
diff --git a/src/OCPikeInterpreter.m b/src/OCPikeInterpreter.m
index 30382803c4..182e27cb4d 100644
--- a/src/OCPikeInterpreter.m
+++ b/src/OCPikeInterpreter.m
@@ -1,57 +1,92 @@
 #import "OCPikeInterpreter.h"
 #import <Foundation/NSString.h>
 #import <Foundation/NSBundle.h>
+#import <Foundation/NSException.h>
 
-static OCPikeInterpreter * si = NULL;
+PMOD_EXPORT OCPikeInterpreter * sharedInstance = nil;
+
+struct Pike_interpreter_struct * Pike_interpreter_pointer;
  
 static void set_master(const char *file)
 {
   if (strlen(file) >= MAXPATHLEN*2 ) {
-    fprintf(stderr, "Too long path to master: \"%s\" (limit:%"PRINTPTRDIFFT"d)\n",
+    fprintf(stderr, "Too long path to master: \"%s\" (limit:%d)\n",
             file, MAXPATHLEN*2 );
     exit(1);
   }
 //  strcpy(master_location, file);
 }
 
-
-static void set_default_master(void)
+ void set_default_master(void)
 {
 }
 
-
-
 @implementation OCPikeInterpreter
-- (id) init 
-{	
-  self = [super init];
-  if(self) 
+
++(OCPikeInterpreter *)sharedInterpreter
+{
+  @synchronized(self)
   {
-    [self retain];
-    master_location = NULL;
+    if ( sharedInstance == nil )
+      [[self alloc] init];
+	
   }
+  return sharedInstance;
+}
 
++ (id)allocWithZone:(NSZone *)zone
+{
+  @synchronized(self) {
+    if (sharedInstance == nil) {
+      sharedInstance = [super allocWithZone:zone];
+      return sharedInstance;
+    }
+  }
+ 
+  return nil;
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
   return self;
 }
 
-+(OCPikeInterpreter *)sharedInterpreter
+- (id)retain
 {
-  if ( si == nil )
-    si = [[self alloc] init];
-	
-  return si;
+  return self;
+}
+ 
+- (void)release
+{
+  // do nothing
+}
+ 
+- (id)autorelease
+{
+  return self;
+}
+ 
+- (NSUInteger)retainCount
+{
+  return NSUIntegerMax; // This is sooo not zero
 }
 
+- (struct Pike_interpreter_struct *) getInterpreter
+{
+  return pike_get_interpreter_pointer();
+}
 
 - (void)setMaster:(id) master
 {
+	
   if ([master length] >= MAXPATHLEN*2 ) 
   {
-    fprintf(stderr, "Too long path to master: \"%s\" (limit:%"PRINTPTRDIFFT"d)\n",
+    fprintf(stderr, "Too long path to master: \"%s\" (limit:%d)\n",
             [master UTF8String], MAXPATHLEN*2 );
 	    exit(1);
    }
    master_location = [master copy];
+
 }
 
 void shared_interpreter_cleanup(int exitcode)
@@ -65,37 +100,38 @@ void shared_interpreter_cleanup(int exitcode)
    int num = 0;
    struct object *m;
    char ** argv = NULL;
-	
-   id ml;
+   char * master;	
    id this_bundle;
-   this_bundle = [NSBundle bundleForClass: [self class]];
 
+   objc_registerThreadWithCollector();
+
+   this_bundle = [NSBundle bundleForClass: [self class]];
    if(!this_bundle || this_bundle == nil)
    {
-	NSException * exception = [NSException exceptionWithName:@"Error finding bundle!" reason:@"bundleForClass: returned nil." userInfo: nil];
-	@throw exception;
+	   NSException * exception = [NSException exceptionWithName:@"Error finding bundle!" reason:@"bundleForClass: returned nil." userInfo: nil];
+  	 @throw exception;
    }
+
    if(!master_location)
    {
-     ml = [[NSMutableString alloc] initWithCapacity: 200];
-     [ml setString: [this_bundle resourcePath]];
-     [ml appendString: @"/lib/master.pike"];
-
-     [self setMaster: ml];
-		
-     [ml release];
-    }
+     id masterPath;
+     masterPath = [[this_bundle resourcePath] stringByAppendingString: @"/lib/master.pike"];     
+     [self setMaster: masterPath];   
+   }
 
-    init_pike(argv, [master_location UTF8String]);
+    master = (char *)[master_location UTF8String];
+    init_pike(argv, master);
     init_pike_runtime(shared_interpreter_cleanup);
 
+    Pike_interpreter_pointer = get_interpreter_pointer();
+
     add_pike_string_constant("__embedded_resource_directory",
-				[[this_bundle resourcePath] UTF8String],
-				strlen([[this_bundle resourcePath] UTF8String]));
+        master,
+        strlen(master));
 								
     add_pike_string_constant("__master_cookie",
-	                           [master_location UTF8String], 
-				strlen([master_location UTF8String]));
+                             master,
+                            strlen(master));
 
     if(SETJMP(jmploc))
     {
@@ -181,9 +217,10 @@ void shared_interpreter_cleanup(int exitcode)
     struct program * p;
     struct svalue * s;
     struct svalue * res;
-    id desc;
+    id desc, c;
 
-    id c = [[NSMutableString alloc] initWithCapacity: 200];
+    objc_registerThreadWithCollector();
+    c = [[NSMutableString alloc] initWithCapacity: 200];
 
     [c setString: @"mixed foo(){ return("];
     [c appendString: expression];
@@ -191,8 +228,6 @@ void shared_interpreter_cleanup(int exitcode)
 
     p = [self compileString: c];
 
-    [c release];
-
     if(!p) return NULL;
  
 	i=find_identifier("foo", p);
@@ -229,20 +264,24 @@ void shared_interpreter_cleanup(int exitcode)
 
 /*
 
-	following is a simple example of how to use OCPikeInterpreter to embed a pike interpreter into your application.
+	following is a simple example of how to use OCPikeInterpreter to embed a pike interpreter into your application,
+	this code relies on GC present in Mac OSX 10.5 +
 
          make framework
          cp -rf Pike.framework /Library/Frameworks
 
-         gcc -I . -c test.m -o test.o
+         gcc -I . -fobjc-gc -c test.m -o test.o
          gcc test.o -o test -framework Pike  -framework Foundation
 
 */
 
 /*
+
 #import <Pike/OCPikeInterpreter.h>
 #import <Foundation/NSString.h>
-#import <Foundation/NSAutoreleasePool.h>
+#import <objc/objc-auto.h>
+
+struct Pike_interpreter_struct * Pike_interpreter_pointer;
 
 int main()
 {
@@ -250,11 +289,12 @@ int main()
   struct svalue * sv;
 
   // required for console mode objective c applications
-  NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init];
+  objc_startCollectorThread();
 
   // these 3 lines set up and start the interpreter.
   i = [OCPikeInterpreter sharedInterpreter];
   [i startInterpreter];
+  Pike_interpreter_pointer = [i getInterpreter];
 
   // ok, now that we have things set up, let's use it.
   // first, an example of calling pike c level apis directly.  
@@ -269,7 +309,7 @@ int main()
 
   // finally, we clean up.
   [i stopInterpreter];
-  [innerPool release];
+
   return 0;
 }
 
diff --git a/src/interpret.c b/src/interpret.c
index 64554858b2..5a9eb1b673 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -125,6 +125,10 @@ static void do_trace_call(INT32 args, dynamic_buffer *old_buf);
 static void do_trace_func_return (int got_retval, struct object *o, int fun);
 static void do_trace_return (int got_retval, dynamic_buffer *old_buf);
 
+PMOD_EXPORT struct Pike_interpreter_struct * pike_get_interpreter_pointer()
+{
+  return Pike_interpreter_pointer;
+}
 
 void push_sp_mark(void)
 {
diff --git a/src/interpret.h b/src/interpret.h
index ce1cd7d76b..8b7d32d17b 100644
--- a/src/interpret.h
+++ b/src/interpret.h
@@ -793,6 +793,7 @@ void low_return_pop(void);
 void unlink_previous_frame(void);
 int apply_low_safe_and_stupid(struct object *o, INT32 offset);
 
+PMOD_EXPORT struct Pike_interpreter_struct * pike_get_interpreter_pointer();
 PMOD_EXPORT void mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2);
 PMOD_EXPORT void f_call_function(INT32 args);
 PMOD_EXPORT void call_handle_error(void);
diff --git a/src/version.c b/src/version.c
index 3b8084cbe4..90ef959e98 100644
--- a/src/version.c
+++ b/src/version.c
@@ -22,7 +22,7 @@
  *!   @[__VERSION__], @[__MINOR__], @[__BUILD__],
  *!   @[__REAL_VERSION__], @[__REAL_MINOR__], @[__REAL_BUILD__],
  */
-void f_version(INT32 args)
+PMOD_EXPORT void f_version(INT32 args)
 {
   pop_n_elems(args);
   push_constant_text ("Pike v"
diff --git a/src/version.h b/src/version.h
index f6b3cd3ab6..535170b96c 100644
--- a/src/version.h
+++ b/src/version.h
@@ -9,6 +9,6 @@
 #define PIKE_BUILD_VERSION 5
 
 /* Prototypes begin here */
-void f_version(INT32 args);
+PMOD_EXPORT void f_version(INT32 args);
 void push_compact_version();
 /* Prototypes end here */
-- 
GitLab