home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / SourceCode / DynamicApp / DynamicApplication.m < prev    next >
Text File  |  1993-01-19  |  6KB  |  239 lines

  1. #import <appkit/Panel.h>    
  2. #import <objc/List.h>
  3. #import <objc/HashTable.h>
  4. #import <objc/objc-load.h>
  5. #import <streams/streams.h>
  6.  
  7. #import <stdio.h>
  8. #import <string.h>
  9. #import <stdlib.h>
  10.  
  11. #import "DynamicApplication.h"
  12.  
  13. #define    DYN_NO_ERROR        0
  14. #define    DYN_NOT_OBJECT_FILE    1
  15. #define DYN_MULTIPLE_FUNCTION    2
  16. #define DYN_MULTIPLE_OBJECT    3
  17. #define DYN_UNDEFINED_FUNCTION    4
  18. #define DYN_UNDEFINED_OBJECT    5
  19. #define DYN_UNKNOWN_ERROR    6
  20.  
  21. char    *errorCodes[7] = {    NULL, 
  22.                 NULL, 
  23.                 "multiple definitions of symbol _",
  24.                 "multiple definitions of symbol .objc_class_name",
  25.                 "Undefined symbols:\n_",
  26.                 "Undefined symbols:\n.objc_class_name",
  27.                 NULL                            };
  28.                 
  29. char    *errorList[7] = {    NULL,
  30.                 NULL,
  31.                 "The Class being loaded contained functions names which conflicted with those already loaded",
  32.                 "The Class being loaded contained Class names which conflicted with those already loaded",
  33.                 "The Class being loaded requires function that are not present in the current executable",
  34.                 "The Class being loaded requires Classes that are not present in the current executable",
  35.                 "An unkown error has occurred at load time"        };
  36.                 
  37. @implementation DynamicApplication
  38.  
  39. void LogInClass( id aClass, id aCategory )
  40. {
  41.     char     *temp_str;
  42.     const char    *className;
  43.     id        temp;
  44.     extern id    NXApp;
  45.     
  46.     temp = [aClass alloc];
  47.     className = [temp name];
  48.     
  49.     if( [[NXApp _dynamicClassesHashTable] isKey:className] )
  50.     {
  51.         fprintf( stderr, "ERROR: A class by the name of %s has already been loaded...\n", className );
  52.     }
  53.     else
  54.     {
  55.         temp_str = malloc( strlen( className ) + 1 * sizeof( char ) );
  56.     strcpy( temp_str, className );
  57.     [[NXApp _dynamicClassesHashTable] insertKey:temp_str value:aClass];
  58.     [NXApp _incrementDynamicClassesNum];
  59.     [NXApp _setLoadedClassInfo:temp_str :aClass];
  60.     }
  61.     
  62.     [temp free];
  63. }
  64.  
  65. void LogOutClass( const char *className )
  66. {    
  67.     extern id    NXApp;
  68.  
  69.     printf("I am logging out %s\n", className);
  70.     
  71.     if( [[NXApp _dynamicClassesHashTable] isKey:className] )
  72.     {
  73.         fprintf( stderr, "ERROR: There is no class %s to be unloaded...\n", className );
  74.     }
  75.     else
  76.     {
  77.     [[NXApp _dynamicClassesHashTable] removeKey:className];
  78.     [NXApp _decrementDynamicClassesNum];
  79.     }
  80. }
  81.  
  82. + new
  83. {
  84.     self = [super new];
  85.     [self init];
  86.     return self;
  87. }
  88.  
  89. - init
  90. {
  91.     self = [super init];
  92.     
  93.     dynamicClasses = [[HashTable alloc] initKeyDesc:"*" valueDesc:"@"];
  94.     dynamicClassesNum = 0;
  95.     errorFlags._errorOnLastLoad = NO;
  96.     errorFlags._classLoaded = NO;
  97.     errorFlags._errorType = DYN_NO_ERROR;
  98.     lastClassInfo._className = NULL;
  99.     
  100.     return self;
  101. }
  102.     
  103. - loadClass:(char *)classPath
  104. {
  105.     char     *objectFileName[2];
  106.     NXStream    *aStream;
  107.     void    (*callback)();
  108.     
  109.     callback = LogInClass;
  110.     
  111.     aStream = NXOpenFile( (fileno( stderr )), NX_READWRITE );
  112.     
  113.     errorFlags._errorOnLastLoad = NO;
  114.     errorFlags._classLoaded = NO;
  115.     errorFlags._errorType = DYN_NO_ERROR;
  116.  
  117.     if( strcmp( strrchr( classPath, '.' ), ".o" ) )
  118.     {
  119.     errorFlags._errorOnLastLoad = YES;
  120.     errorFlags._classLoaded = NO;
  121.     errorFlags._errorType = DYN_NOT_OBJECT_FILE;
  122.     NXRunAlertPanel("Load Error", "This version of DynamicApplication will only load '.o' object files", 
  123.             "OK", NULL, NULL);
  124.     }
  125.     else
  126.     {
  127.         objectFileName[0] = classPath;
  128.         objectFileName[1] = NULL;
  129.     
  130.         if( objc_loadModules( objectFileName, aStream, callback, NULL, NULL ) )
  131.     {
  132.         errorFlags._errorOnLastLoad = YES;
  133.         errorFlags._classLoaded = NO;
  134.         errorFlags._errorType = [self _parseErrorStream:aStream];
  135.     }
  136.     }
  137.  
  138.     NXClose( aStream );
  139.     
  140.     return [self classWithName:lastClassInfo._className];
  141. }
  142.  
  143. - loadClass:(char *)classPath withName:(char *)className
  144. {
  145.     char *temp_str;        // Don't free this key (hashTable needs it)
  146.     
  147.     temp_str = malloc( strlen( className ) + 1 * sizeof( char ) );
  148.     strcpy( temp_str, className );
  149.     
  150.     [self loadClass:classPath];
  151.     [dynamicClasses insertKey:temp_str value:[dynamicClasses valueForKey:lastClassInfo._className]];
  152.     lastClassInfo._className = temp_str;
  153.     
  154.     return [self classWithName:className];
  155. }
  156.  
  157. - getClassNameList:(char **)classList
  158. {
  159.     char    *key;
  160.     id        *value;
  161.     int        count = 0;
  162.     
  163.     NXHashState state = [dynamicClasses initState];
  164.     
  165.     while([dynamicClasses nextState:&state key:&key value:&value])
  166.         classList[count++] = key;
  167.     
  168.     return self;
  169. }
  170.         
  171. - (int)classesNum { return dynamicClassesNum; }
  172.  
  173. - (char *)lastClassName { return lastClassInfo._className; }
  174. - lastClass { return [self classWithName:[self lastClassName]]; }
  175.  
  176. - (BOOL)errorOnLastLoad { return errorFlags._errorOnLastLoad; }
  177. - (unsigned int)errorType { return errorFlags._errorType; }
  178. - (BOOL)classLoaded { return errorFlags._classLoaded; }
  179.  
  180. - classWithName:(char *)className
  181. {
  182.     return [dynamicClasses valueForKey:className];
  183. }
  184.  
  185. - removeClassWithName:(char *)className
  186. {
  187.     [dynamicClasses removeKey:className];    // cheap, lame, boooo hisssss;
  188.     return self;
  189. }
  190.  
  191. - free
  192. {
  193.     [dynamicClasses freeObjects];
  194.     [dynamicClasses free];
  195.     free( lastClassInfo._className );
  196.     free( &dynamicClassesNum );
  197.     
  198.     [super free];
  199.     
  200.     return nil;
  201. }
  202.  
  203. - _dynamicClassesHashTable { return dynamicClasses; }
  204. - _incrementDynamicClassesNum { dynamicClassesNum++; return self; }
  205. - _decrementDynamicClassesNum { dynamicClassesNum--; return self; }
  206.  
  207. - _setLoadedClassInfo:(char *)className :(Class)aClass
  208. {
  209.     free( lastClassInfo._className );
  210.     lastClassInfo._className = malloc( strlen( className ) + 1 * sizeof( char ) );
  211.     strcpy( lastClassInfo._className, className );
  212.     
  213.     errorFlags._classLoaded = YES;
  214.     
  215.     return self;
  216. }
  217.  
  218. - (unsigned int)_parseErrorStream:(NXStream *)aStream
  219. {
  220.     char     *errorBuffer;
  221.     int        i;
  222.     
  223.     errorBuffer = aStream->buf_base;
  224.        
  225.     for( i = 2 ; i < 7 ; i++ )
  226.         if( strstr( errorBuffer, errorCodes[i] ) )
  227.         {
  228.         NXRunAlertPanel( "Load Error", errorList[i], "OK", NULL, NULL );
  229.         break;
  230.         }
  231.  
  232.     if( i == 6 )
  233.         NXRunAlertPanel( "Load Error", errorList[i], "OK", NULL, NULL );
  234.     
  235.     return i;
  236. }
  237.  
  238. @end
  239.