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.