This is ClassManager.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "ClassManager.h" #import "MenuManager.h" #import <appkit/Application.h> #import <appkit/Text.h> #import <appkit/Panel.h> #import <appkit/NXBrowser.h> #import <objc/objc-load.h> #import <objc/Storage.h> #import <libc.h> #import <strings.h> id loadList ; // this global var points to a "Storage" list of // 2-element malloced arrays of chars, where element // 0 contains the classname and element 1 contains // the pathname of every loaded class struct loadClass { char *className ; char *dotOFileName ; } ; @implementation ClassManager: WindowManager + initialize ; // initialize the loadList { loadList = [[Storage new] initCount:0 elementSize: sizeof(struct loadClass) description:"{**}"] ; return [super initialize] ; } +(int) loadIndex: (char *) nameOfClass ; // if nameOfClass is in the load list, return its index, // else return -1 { int i, knt ; struct loadClass *lc ; knt = [loadList count] ; for(i = 0 ; i < knt ; i++) { lc = (struct loadClass *) [loadList elementAt: i] ; if(!strcmp(lc->className, nameOfClass)) return i ; } return -1 ; } + loadList ; { return loadList ; } + unload: (const char *) aClass; // unload the class with name aClass { char *moduleNames[2], *textBuf ; int i, loadNumber, loadKnt, textLen, maxLen ; struct loadClass *lcPtr ; NXStream *aStream ; aStream = NXOpenMemory(NULL, 0, NX_READWRITE) ; loadKnt = [loadList count] ; moduleNames[1] = NULL ; loadNumber = [ClassManager loadIndex: (char *) aClass] ; if(loadNumber != -1) // module is loaded... { for(i = loadKnt ; i > loadNumber ; i--) objc_unloadModules(aStream, NULL) ; // unload all classes lcPtr = [loadList elementAt: i] ; free(lcPtr->className) ; free(lcPtr->dotOFileName) ; [loadList removeAt: i] ; // remove this class from loadList loadKnt-- ; for( ; i < loadKnt ; i++) // reload unloaded classes { lcPtr = (struct loadClass *) [loadList elementAt: i] ; moduleNames[0] = lcPtr->dotOFileName ; objc_loadModules(moduleNames, aStream, NULL, NULL, NULL) ; } } NXGetMemoryBuffer(aStream, &textBuf, &textLen, &maxLen); [NXApp printf: textBuf]; NXCloseMemory(aStream,NX_TRUNCATEBUFFER) ; [[NXApp loadedClassesBrowser] loadColumnZero] ; return self ; } + unloadAll ; // unload all incrementally loaded classes { char *textBuf ; NXStream *aStream ; int i, loadKnt, textLen, maxLen ; struct loadClass *lcPtr ; loadKnt = [loadList count] ; aStream = NXOpenMemory(NULL, 0, NX_READWRITE) ; for(i = 0 ; i < loadKnt ; i++) { objc_unloadModules(aStream, NULL) ; lcPtr = [loadList elementAt: 0] ; free(lcPtr->className) ; free(lcPtr->dotOFileName) ; [loadList removeAt: 0] ; } NXGetMemoryBuffer(aStream, &textBuf, &textLen, &maxLen); [NXApp printf: textBuf]; NXCloseMemory(aStream,NX_TRUNCATEBUFFER) ; [[NXApp loadedClassesBrowser] loadColumnZero] ; [[NXApp loadedClassesBrowser] loadColumnZero] ; return self ; } - className: (char *) name ; { // copy className into ivar strncpy(className, name, 63) ; return self ; } - classText: (char *) theText ; { // copy theText into text object [textView setText: theText] ; [self setDocEdited:YES]; return self ; } - compile:sender { char buf[512] ; char tmpFile[20] = "CBXXXXXX" ; if([self isDocEdited]) // be sure file is saved first [self save: self] ; // use awk to create .h file. We should probably refine // this script. it can't deal with @implementation a:b, there // must be a blank after the colon, thus a: b mktemp(tmpFile) ; [self message: "Creating .h file..."] ; sprintf(buf, "awk '\\\n\ /#pragma .h/ { $1 = \"\";$2=\"\"; print}\\\n\ /@implementation/ { $1 = \"@interface\"; print ;state++ }\\\n\ /^{/ { if(state == 1) state++ }\\\n\ { if(state == 2) print }\\\n\ /^}/ { if(state == 2) state++ }\\\n\ /^[+-]/ { if(state == 3) print }\\\n\ END { print \"@end\"}'\\\n\ < %s.m > %s.h",className, className, className ) ; system(buf) ; // compile into .o file sprintf(buf, "cc -c -I /usr/include/objc -Wall -o %s.o %s.m" " 2> /tmp/%s", className, className, tmpFile) ; [self message: "Compiling..."] ; if(system(buf)) // non-zero exit status == errors { sprintf(buf,"/tmp/%s",tmpFile) ; [NXApp appendFileToTranscript: buf] ; NXRunAlertPanel("CB","Compilation errors: see Transcript Window\n", NULL,NULL,NULL) ; sprintf(buf,"rm /tmp/%s.m /tmp/%s.o /tmp/%s 2> /dev/null", tmpFile,tmpFile,tmpFile) ; system(buf) ; } [self message: ""] ; return self ; } - (char *) extension ; { // provide file extension return "m" ; } - load:sender ; { char *moduleNames[2] ; struct loadClass lc ; NXStream *aStream ; aStream = NXOpenMemory(NULL, 0, NX_READWRITE) ; moduleNames[1] = NULL ; // if class is already loaded, we'll have to unload // all classes loaded after it, then reload all unloaded // classes except it. [self message: "Loading..."] ; [ClassManager unload: className] ; // load current module. Note that we have moved the module // to the end of the loadlist, so subsequent reloads of // it are quicker. lc.className = malloc(strlen(className) + 1) ; strcpy(lc.className,className) ; lc.dotOFileName = malloc(strlen(fileName) + 1) ; strcpy(lc.dotOFileName,fileName) ; lc.dotOFileName[strlen(lc.dotOFileName) -1] = 'o' ; moduleNames[0] = lc.dotOFileName ; objc_loadModules(moduleNames, aStream, NULL, NULL, NULL) ; [loadList addElement: (void *) &lc] ; NXSeek(aStream, 0L, NX_FROMSTART) ; NXCloseMemory(aStream,NX_TRUNCATEBUFFER) ; [[NXApp loadedClassesBrowser] loadColumnZero] ; [self message: ""] ; return self ; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.