This is ModuleMgr.m in view mode; [Download] [Up]
#import "ModuleMgr.h" #import "TokenString.h" #import "Directory.h" #import "NXGets.h" @implementation ModuleMgr - initForPaths: (const char *)aPath fileType: (const char *)aType { [super initKeyDesc: "*"]; paths = [[StringStorage alloc] init: aPath]; if(!*[paths stringValue]) { [paths setStringValue: "/LocalLibrary/%s:~/Library/%s"]; [paths replaceSubstring: "%s" with: [NXApp appName]]; [paths replaceSubstring: "%s" with: [NXApp appName]]; } NXLogError("Looking for modules in %s", [paths stringValue]); fileType = [[StringStorage alloc] init: aType]; features = (Protocol *)0; [self loadModules]; return self; } - setFeatures: (Protocol *) aProtocol { features = aProtocol; return self; } - loadModules { int cnt; const char *aPath; id modules = [[Directory alloc] init]; id path = [[TokenString alloc] init: [paths stringValue]]; id pattern = [[StringStorage alloc] init: "*."]; [path setSeparator: ':']; [pattern appendStringValue: [fileType stringValue]]; while(aPath = [path popStringValue]) { [modules setPath: aPath]; if([modules count] && ( cnt = [modules select: [pattern stringValue]])) { int x; id sendModules = [modules selectedFiles]; id modulePath; char *moduleName; /* * Create a hash of the modules. Use the name and path until the module is needed * And the the path will be converted to a bundle. */ for(x = 0; x < cnt; x++) { NX_MALLOC(moduleName, char,[[sendModules objectAt: x] count]); strcpy(moduleName, [[sendModules objectAt: x] stringValue]); modulePath = [[StringStorage alloc] init: [modules path]]; [modulePath appendCharValue: '/']; [modulePath appendStringValue: moduleName]; moduleName[strlen(moduleName) - (strlen([fileType stringValue]) + 1)] = (char)0; /* clip off .sndO */ [self insertKey: moduleName value: modulePath]; if(![self isKey: moduleName]) NXLogError("Hash failed\n"); } } } [pattern free]; [modules free]; [path free]; return self; } - loadFileType: (const char *)aType { return self; } - free { [paths free]; [fileType free]; return [super free]; } - getModule: (const char *)moduleName { id bundle = (id)[self valueForKey: moduleName]; id loaded, primeClass; char modulePath[MAXPATHLEN]; char *newKey; if(!bundle) { const char *aKey; [self initState]; NXLogError("Could not find hash entry: (%s)\n", moduleName); while (aKey = [self nextKey]); NXLogError("moduleName: %s", aKey); return nil; } if([bundle isKindOf: [NXBundle class]]) return bundle; if(![bundle isKindOf: [StringStorage class]]) { NXLogError("Hash stored bad item..."); return nil; } /* Bundle was not yet loaded - do so. */ NXLogError("Need to load: %s", [bundle stringValue]); loaded = [[NXBundle alloc] initForDirectory: [bundle stringValue]]; if(!loaded) { NXLogError("failed to load\n"); return nil; } /* insert the real bundle into the hash now to replace the place holder */ NX_MALLOC(newKey, char, strlen(moduleName)); /* allocate another key - this is a bug in HashTable I feel */ strcpy(newKey, moduleName); [self insertKey: newKey value: loaded]; [bundle free]; /* free up the path/place holder */ bundle = loaded; /* * Before we resolve the symbols in the bundle see if it needs any * other bundles loaded as ancestors. */ if([bundle getPath: modulePath forResource: "inheritance" ofType: ""]) { NXStream *sp; char parentsBuf[128]; const char *parent; id parents; sp = NXMapFile(modulePath, NX_READONLY); if(!sp) { NXLogError("Couldn't open %s\n", [bundle stringValue]); return nil; } NXGets(parentsBuf, 128, sp); NXClose(sp); /* Get known parrents and load them */ parents = [[TokenString alloc] init: parentsBuf]; while(parent = [parents popStringValue]) if(![self getModule: parent]) { NXLogError("Ancestor failed to load...\n"); return nil; } [parents free]; } if(!(primeClass = [bundle principalClass])) { /* make rld resolve names */ NXLogError("Corruoted bundle: %s\n", moduleName); return nil; } if(features) { if(![primeClass conformsTo: features]) { NXLogError("Bundle's principal class does not conform to %s protocol.", [features name]); return nil; } } return bundle; } - (NXHashState) initState { state = [super initState]; return state; } - (const char *)nextKey { static const void *key, *value; if([self nextState: &state key: &key value: &value]) return (const char *)key; else return (const char *)0; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.