This is COWSObjectLibrary.m in view mode; [Download] [Up]
// Formalities
// Copyright (C) 1994 Guus C. Bloemsma
//
// COWSObjectLibrary.m
// Version 1.0 Guus C. Bloemsma
#import "COWSObjectLibrary.h"
@interface Object(findClass)
// A hack to declare the findClass: method that is apparently nowhere documented
// but can be found in AppInspector, the most amazing tool ever made (right after
// Interface Builder ;-)
- (Class) findClass: (const char *) className;
@end
@implementation COWSStringNode(ObjectLibrary)
- idVal {
if (SN_CHECK([self value_state], COWSSTRINGNODE_STORED_STRING))
return NXGetNamedObject(string, NXApp);
else
return (id)(long)double_value;
};
- setIdVal: object {
return [self setDoubleVal:(long)object];
};
- classVal {
if (SN_CHECK([self value_state], COWSSTRINGNODE_STORED_STRING))
/* ignore warning */
return [self findClass:string];
else
return (id)(long)double_value;
};
- setClassVal: object {
return [self setDoubleVal:(long)object];
};
- (SEL) selVal {
if (SN_CHECK([self value_state], COWSSTRINGNODE_STORED_STRING))
return sel_getUid(string);
else
return (SEL)(long)double_value;
};
- setSelVal: (SEL)selector {
return [self setDoubleVal:(long)selector];
};
@end
@implementation COWSObjectLibrary
id objc_msgSendv(id theReceiver, SEL theSelector, unsigned int argSize, marg_list argFrame);
char *ObjectMakeStack (marg_list stack, unsigned long maxStackSize, Method theMethod,
id parameters, unsigned int *stackSize) {
// Need a lot more error checking and optimization here
unsigned int size;
unsigned int count;
unsigned int index;
size = method_getSizeOfArguments(theMethod);
count = method_getNumberOfArguments(theMethod);
if (size > maxStackSize)
return "Too many arguments.\n";
for (index = 2; index < count; index++) {
const char *type;
int offset;
id param = [parameters next];
method_getArgumentInfo(theMethod, index, &type, &offset);
//printf("Passing type \"%s\" at offset %d\n", type, offset);
switch (*type) {
case 'c': // A char
marg_setValue(stack, offset, char, [param intVal]);
break;
case 'i': // An int
marg_setValue(stack, offset, int, [param intVal]);
break;
case 's': // A short
marg_setValue(stack, offset, short, [param intVal]);
break;
case 'l': // A long
marg_setValue(stack, offset, long, [param intVal]);
break;
case 'C': // An unsigned char
marg_setValue(stack, offset, unsigned char, [param intVal]);
break;
case 'I': // An unsigned int
marg_setValue(stack, offset, unsigned int, [param intVal]);
break;
case 'S': // An unsigned short
marg_setValue(stack, offset, unsigned short, [param intVal]);
break;
case 'L': // An unsigned long
marg_setValue(stack, offset, unsigned long, [param intVal]);
break;
case 'f': // A float
marg_setValue(stack, offset, float, [param floatVal]);
break;
case 'd': // A double
marg_setValue(stack, offset, double, [param floatVal]);
break;
case 'v': // A void
break;
case '*': // A character string (char *)
// żż make this an NXAtom first?
marg_setValue(stack, offset, const char *, [param string]);
break;
case '@': // An object (whether statically typed or typed id)
marg_setValue(stack, offset, id, [param idVal]);
break;
case '#': // A class object (Class)
// żż Take class of object ?
marg_setValue(stack, offset, Class, [param classVal]);
break;
case ':': // A method selector (SEL)
marg_setValue(stack, offset, SEL, [param selVal]);
break;
case '[': //...] An array
case '{': //...} A structure
case '(': //...) A union
case 'b': //num A bitfield of num bits
case '^': //type A pointer to type
case '?': // An unknown type
default:
return "Method expects composite type.";
};
};
if (stackSize)
*stackSize = size;
return NULL;
};
- object_to: arg_list {
id result=[[COWSStringNode alloc] init];
id arg = [arg_list first];
const char *messageName;
SEL selector;
char myStack[1024];
id object;
unsigned int stackSize;
Method theMethod;
arg = [arg_list first];
if ((!arg) || !((object = [arg idVal]) || (object = [arg classVal])))
return [[result setError: YES] setString: "\"to\" needs an object or class"];
arg = [arg_list next];
if ((!arg) || !(messageName = [arg string]))
return [[result setError: YES] setString: "\"to\" needs a message name"];
selector = sel_getUid(messageName);
if (!selector)
return [[result setError: YES] setString: "this is not a selector"];
/* ignore warning */
theMethod = class_getInstanceMethod(object->isa, selector);
if (!theMethod)
return [[result setError: YES] setString: "the object does not respond to this selector"];
ObjectMakeStack (myStack, 1024, theMethod, arg_list, &stackSize);
switch (*theMethod->method_types) {
case 'c': // A char
[result setBooleanVal: ((char(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'i': // An int
[result setIntVal: ((int(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 's': // A short
[result setIntVal: ((short(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'l': // A long
[result setIntVal: ((long(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'C': // An unsigned char
[result setBooleanVal: ((unsigned char(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'I': // An unsigned int
[result setIntVal: ((unsigned int(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'S': // An unsigned short
[result setIntVal: ((unsigned short(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'L': // An unsigned long
[result setIntVal: ((unsigned long(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'f': // A float
[result setFloatVal: ((float(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'd': // A double
[result setDoubleVal: ((double(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case 'v': // A void
objc_msgSendv(object, selector, stackSize, myStack);
break;
case '*': // A character string (char *)
[result setString: ((char*(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case '@': // An object (whether statically typed or typed id)
[result setIdVal: objc_msgSendv(object, selector, stackSize, myStack)];
break;
case '#': // A class object (Class)
[result setClassVal: objc_msgSendv(object, selector, stackSize, myStack)];
break;
case ':': // A method selector (SEL)
[result setSelVal: ((SEL(*)(id, SEL, unsigned int, marg_list)) objc_msgSendv) (object, selector, stackSize, myStack)];
break;
case '[': //...] An array
case '{': //...} A structure
case '(': //...) A union
case 'b': //num A bitfield of num bits
case '^': //type A pointer to type
case '?': // An unknown type
default:
[[result setError: YES] setString: "cannot return this type"];
};
return result;
}
- loadLibrary:sender {
id result = [super loadLibrary:sender];
if (![sender conformsTo:@protocol(LibraryControl)]) {
puts ("ObjectLibrary error: "
"Interpreter doesn't conform to LibraryControl!");
return NULL;
}
[sender addLibraryFunction: "to"
selector:@selector(object_to:)
target:self];
return result;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.