home *** CD-ROM | disk | FTP | other *** search
- #import <appkit/Panel.h>
- #import <objc/List.h>
- #import <objc/HashTable.h>
- #import <objc/objc-load.h>
- #import <streams/streams.h>
-
- #import <stdio.h>
- #import <string.h>
- #import <stdlib.h>
-
- #import "DynamicApplication.h"
-
- #define DYN_NO_ERROR 0
- #define DYN_NOT_OBJECT_FILE 1
- #define DYN_MULTIPLE_FUNCTION 2
- #define DYN_MULTIPLE_OBJECT 3
- #define DYN_UNDEFINED_FUNCTION 4
- #define DYN_UNDEFINED_OBJECT 5
- #define DYN_UNKNOWN_ERROR 6
-
- char *errorCodes[7] = { NULL,
- NULL,
- "multiple definitions of symbol _",
- "multiple definitions of symbol .objc_class_name",
- "Undefined symbols:\n_",
- "Undefined symbols:\n.objc_class_name",
- NULL };
-
- char *errorList[7] = { NULL,
- NULL,
- "The Class being loaded contained functions names which conflicted with those already loaded",
- "The Class being loaded contained Class names which conflicted with those already loaded",
- "The Class being loaded requires function that are not present in the current executable",
- "The Class being loaded requires Classes that are not present in the current executable",
- "An unkown error has occurred at load time" };
-
- @implementation DynamicApplication
-
- void LogInClass( id aClass, id aCategory )
- {
- char *temp_str;
- const char *className;
- id temp;
- extern id NXApp;
-
- temp = [aClass alloc];
- className = [temp name];
-
- if( [[NXApp _dynamicClassesHashTable] isKey:className] )
- {
- fprintf( stderr, "ERROR: A class by the name of %s has already been loaded...\n", className );
- }
- else
- {
- temp_str = malloc( strlen( className ) + 1 * sizeof( char ) );
- strcpy( temp_str, className );
- [[NXApp _dynamicClassesHashTable] insertKey:temp_str value:aClass];
- [NXApp _incrementDynamicClassesNum];
- [NXApp _setLoadedClassInfo:temp_str :aClass];
- }
-
- [temp free];
- }
-
- void LogOutClass( const char *className )
- {
- extern id NXApp;
-
- printf("I am logging out %s\n", className);
-
- if( [[NXApp _dynamicClassesHashTable] isKey:className] )
- {
- fprintf( stderr, "ERROR: There is no class %s to be unloaded...\n", className );
- }
- else
- {
- [[NXApp _dynamicClassesHashTable] removeKey:className];
- [NXApp _decrementDynamicClassesNum];
- }
- }
-
- + new
- {
- self = [super new];
- [self init];
- return self;
- }
-
- - init
- {
- self = [super init];
-
- dynamicClasses = [[HashTable alloc] initKeyDesc:"*" valueDesc:"@"];
- dynamicClassesNum = 0;
- errorFlags._errorOnLastLoad = NO;
- errorFlags._classLoaded = NO;
- errorFlags._errorType = DYN_NO_ERROR;
- lastClassInfo._className = NULL;
-
- return self;
- }
-
- - loadClass:(char *)classPath
- {
- char *objectFileName[2];
- NXStream *aStream;
- void (*callback)();
-
- callback = LogInClass;
-
- aStream = NXOpenFile( (fileno( stderr )), NX_READWRITE );
-
- errorFlags._errorOnLastLoad = NO;
- errorFlags._classLoaded = NO;
- errorFlags._errorType = DYN_NO_ERROR;
-
- if( strcmp( strrchr( classPath, '.' ), ".o" ) )
- {
- errorFlags._errorOnLastLoad = YES;
- errorFlags._classLoaded = NO;
- errorFlags._errorType = DYN_NOT_OBJECT_FILE;
- NXRunAlertPanel("Load Error", "This version of DynamicApplication will only load '.o' object files",
- "OK", NULL, NULL);
- }
- else
- {
- objectFileName[0] = classPath;
- objectFileName[1] = NULL;
-
- if( objc_loadModules( objectFileName, aStream, callback, NULL, NULL ) )
- {
- errorFlags._errorOnLastLoad = YES;
- errorFlags._classLoaded = NO;
- errorFlags._errorType = [self _parseErrorStream:aStream];
- }
- }
-
- NXClose( aStream );
-
- return [self classWithName:lastClassInfo._className];
- }
-
- - loadClass:(char *)classPath withName:(char *)className
- {
- char *temp_str; // Don't free this key (hashTable needs it)
-
- temp_str = malloc( strlen( className ) + 1 * sizeof( char ) );
- strcpy( temp_str, className );
-
- [self loadClass:classPath];
- [dynamicClasses insertKey:temp_str value:[dynamicClasses valueForKey:lastClassInfo._className]];
- lastClassInfo._className = temp_str;
-
- return [self classWithName:className];
- }
-
- - getClassNameList:(char **)classList
- {
- char *key;
- id *value;
- int count = 0;
-
- NXHashState state = [dynamicClasses initState];
-
- while([dynamicClasses nextState:&state key:&key value:&value])
- classList[count++] = key;
-
- return self;
- }
-
- - (int)classesNum { return dynamicClassesNum; }
-
- - (char *)lastClassName { return lastClassInfo._className; }
- - lastClass { return [self classWithName:[self lastClassName]]; }
-
- - (BOOL)errorOnLastLoad { return errorFlags._errorOnLastLoad; }
- - (unsigned int)errorType { return errorFlags._errorType; }
- - (BOOL)classLoaded { return errorFlags._classLoaded; }
-
- - classWithName:(char *)className
- {
- return [dynamicClasses valueForKey:className];
- }
-
- - removeClassWithName:(char *)className
- {
- [dynamicClasses removeKey:className]; // cheap, lame, boooo hisssss;
- return self;
- }
-
- - free
- {
- [dynamicClasses freeObjects];
- [dynamicClasses free];
- free( lastClassInfo._className );
- free( &dynamicClassesNum );
-
- [super free];
-
- return nil;
- }
-
- - _dynamicClassesHashTable { return dynamicClasses; }
- - _incrementDynamicClassesNum { dynamicClassesNum++; return self; }
- - _decrementDynamicClassesNum { dynamicClassesNum--; return self; }
-
- - _setLoadedClassInfo:(char *)className :(Class)aClass
- {
- free( lastClassInfo._className );
- lastClassInfo._className = malloc( strlen( className ) + 1 * sizeof( char ) );
- strcpy( lastClassInfo._className, className );
-
- errorFlags._classLoaded = YES;
-
- return self;
- }
-
- - (unsigned int)_parseErrorStream:(NXStream *)aStream
- {
- char *errorBuffer;
- int i;
-
- errorBuffer = aStream->buf_base;
-
- for( i = 2 ; i < 7 ; i++ )
- if( strstr( errorBuffer, errorCodes[i] ) )
- {
- NXRunAlertPanel( "Load Error", errorList[i], "OK", NULL, NULL );
- break;
- }
-
- if( i == 6 )
- NXRunAlertPanel( "Load Error", errorList[i], "OK", NULL, NULL );
-
- return i;
- }
-
- @end
-