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.