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