This is cfuncs.c in view mode; [Download] [Up]
/*********************************************************************** ***********************************************************************/ #import <objc/objc-runtime.h> #import <objc/objc-load.h> #import <objc/objc-class.h> #import <objc/objc.h> #import "./objclib/STObjectAdditions.h" #import "gst.h" extern void defineCFunc(); BOOL hasUnderscore(const char *string); char *decodeTypeForST(const char *type); id createInstance(id aClass); SEL methodSelelector(Method aMethod); char *methodName(Method aMethod); int numberOfClassMethodsFor(id aClass); Method classMethodFor(id aClass, int at); int numberOfInstanceMethodsFor(id aClass); Method instanceMethodFor(id aClass, int at); char *returnTypeForMethod(Method aMethod); OOP argTypeArrayForMethod(Method aMethod); char *stMethodNameForMethod(Method aMethod); char *stMsgSendNameForMethod(Method aMethod); char *stMsgSendSelectorForMethod(Method aMethod); id subclassOf(id aClass, int at); int numberOfSubclassesOf(id aClass); int returnTypeIsIDForMethod(Method aMethod); int idsAreEqual(id first, id second); int forwardToSmalltalk(id aClass, SEL aSelector); void initUserCFuncs() { /* * ObjCClass methods */ defineCFunc("createInstance", createInstance); defineCFunc("getInstanceMethod", class_getInstanceMethod); defineCFunc("getClassMethod", class_getClassMethod); defineCFunc("getInstanceVariable", class_getInstanceVariable); defineCFunc("poseAs", class_poseAs); defineCFunc("getClass", objc_getClass); defineCFunc("lookUpClass", objc_lookUpClass); defineCFunc("getMetaClass", objc_getMetaClass); defineCFunc("getClasses", objc_getClasses); defineCFunc("loadModules", objc_loadModules); defineCFunc("unloadModules", objc_unloadModules); /* * Stuff written by me */ defineCFunc("methodSelelector", methodSelelector); defineCFunc("methodName", methodName); defineCFunc("numberOfInstanceMethodsFor", numberOfInstanceMethodsFor); defineCFunc("instanceMethodFor", instanceMethodFor); defineCFunc("numberOfClassMethodsFor", numberOfClassMethodsFor); defineCFunc("classMethodFor", classMethodFor); defineCFunc("returnTypeForMethod", returnTypeForMethod); defineCFunc("argTypeArrayForMethod", argTypeArrayForMethod); defineCFunc("stMethodNameForMethod", stMethodNameForMethod); defineCFunc("stMsgSendNameForMethod", stMsgSendNameForMethod); defineCFunc("stMsgSendSelectorForMethod", stMsgSendSelectorForMethod); defineCFunc("numberOfSubclassesOf", numberOfSubclassesOf); defineCFunc("subclassOf", subclassOf); defineCFunc("returnTypeIsIDForMethod", returnTypeIsIDForMethod); defineCFunc("idsAreEqual", idsAreEqual); defineCFunc("forwardToSmalltalk", forwardToSmalltalk); /* * ObjCMethod methods */ /* defineCFunc("getValue", marg_getValue); defineCFunc("getRef", marg_getRef); defineCFunc("setValue", marg_setValue); */ defineCFunc("getNumberOfArguments", method_getNumberOfArguments); defineCFunc("getSizeOfArguments", method_getSizeOfArguments); defineCFunc("getArgumentInfo", method_getArgumentInfo); defineCFunc("getUid", sel_getUid); defineCFunc("getName", sel_getName); defineCFunc("isMapped", sel_isMapped); /* * ObjCObject methods */ defineCFunc("msgSend", objc_msgSend); defineCFunc("getIndexedIvars", object_getIndexedIvars); defineCFunc("setInstanceVariable", object_setInstanceVariable); defineCFunc("getInstanceVariable", object_getInstanceVariable); defineCFunc("getClassName", object_getClassName); } // ============================================================ // Function: // Args: // Description: // ============================================================ id createInstance(id aClass) { return class_createInstance(aClass, (((struct objc_class *)aClass)->instance_size)); } // ============================================================ // Function: // Args: // Description: // ============================================================ char *decodeTypeForST(const char *type) { switch(type[0]) { case '@': case '#': case ':': case '^': return "cObject"; case 'c': return "char"; case 'C': return "char"; case 'i': return "int"; case 'I': return "int"; case 'l': return "long"; case 'L': return "long"; case 's': return "int"; // should be short case 'S': return "int"; case 'f': return "float"; case 'd': return "double"; case '*': return "string"; case 'v': return "void"; } return "unknown"; } /* * stMsgSendNameForMethod return the string used to create * a c callout to the function objc_msgSend with the casts * to the corrent return type and args */ // ============================================================ // Function: stMsgSendNameForMethod // Args: Method // Description: Creates a string that smalltalk uniquely // describe the return and arg types for a objc_msgSend // call. For instance, the if the method drawSelf // was passed in, we would return // cObjectMsgSend: andId sel: aSelector argcObject: arg1 argint: arg2 // ============================================================ char *stMsgSendNameForMethod(Method aMethod) { static char msgSendString[1024]; static char argString[32]; char *type; int offset; int i, argCount = (method_getNumberOfArguments(aMethod) - 2); sprintf(msgSendString, "%sMsgSend%d: anId sel: aSelector", returnTypeForMethod(aMethod), argCount); if (argCount > 0) { for (i=0 ; i<argCount ; i++) { method_getArgumentInfo(aMethod, i+2, &type, &offset); sprintf(argString, " arg%s: arg%d", decodeTypeForST(type), i); strcat(msgSendString, argString); } } return msgSendString; } // ============================================================ // Function: stMsgSendSelectorForMethod // Args: Method // Description: Returns a selector string that smalltalk can // use to identify a selector. If the method for drawSelf:: // was passed in we would return // cObjectMsgSend:sel:argcObject:argint: // ============================================================ char *stMsgSendSelectorForMethod(Method aMethod) { static char msgSendString[1024]; static char argString[32]; char *type; int offset; int i, argCount = (method_getNumberOfArguments(aMethod) - 2); sprintf(msgSendString, "%sMsgSend%d:sel:", returnTypeForMethod(aMethod), argCount); if (argCount > 0) { for (i=0 ; i<argCount ; i++) { method_getArgumentInfo(aMethod, i+2, &type, &offset); sprintf(argString, "arg%s:", decodeTypeForST(type), i); strcat(msgSendString, argString); } } return msgSendString; } /* * stMethodNameForMethod returns the string used to create the * actual smalltalk method. This method will then call the * msgSend ObjCRTInterface class method * XXXMsqSendX: anId sel: aSelector arg1: anArg1 .... argN: anArgN */ // ============================================================ // Function: stMethodNameForMethod // Args: Method // Description: This the name of the method in smalltalk // including arg names. The method for smalltalk would // be returned as drawSelf: arg1 anArg: arg2. Notice that // anArg was added to the name. That is because GNU smalltalk // doesn't recognize ':' as part of a selector name. // ============================================================ char *stMethodNameForMethod(Method aMethod) { char *start = methodName(aMethod); char end[1024]; char argString[32]; //char *aChar[1], *prevChar[1]; char aChar[1], prevChar[1]; int argCount = 0, i, len = strlen(start); end[0] = '\0'; for (i=0 ; i<len ; i++) { aChar[0] = start[i]; if ((start[i] == ':') && (prevChar[0] == ':')) { sprintf(argString, "anArg: arg%d ", argCount); strcat(end, argString); argCount++; } else if (start[i] == ':') { sprintf(argString, ": arg%d ", argCount); strcat(end, argString); argCount++; } else { aChar[1] = '\0'; strcat(end, aChar); } prevChar[0] = aChar[0]; } return end; } // ============================================================ // Function: returnTypeIsIDForMethod // Args: Method // Description: Returns 1 if aMethod returns an Id and // 0 if not. // ============================================================ int returnTypeIsIDForMethod(Method aMethod) { if (aMethod->method_types[0] == '@') return 1; return 0; } // ============================================================ // Function: idsAreEqual // Args: two id's // Description: Return one if both id's are equal and 0 if not. // ============================================================ int idsAreEqual(id first, id second) { if (first == second) return 1; return 0; } // ============================================================ // Function: returnTypeForMethod // Args: Method // Description: Returns a smalltalk type that describes the // return type of a method. If the return type is not a // standard C type we return unknown. // ============================================================ char *returnTypeForMethod(Method aMethod) { int len; char *temp; char *typeString; temp = decodeTypeForST(aMethod->method_types); // We can't have float as a return type, but it will automatically // be promoted to a double by this piece of magic. if (strcmp(temp, "float") == 0) return "double"; return temp; } // ============================================================ // Function: argTypeArrayForMethod // Args: Method // Description: returns an smalltalk array (an OOP) that // contains symbols for each argument type. // ============================================================ OOP argTypeArrayForMethod(Method aMethod) { /* int i, offset, count; const char *type; char array[1024]; array[0] = '\0'; strcat(array, "( cObject cObject "); // for the id and sel for (i=2 ; i < method_getNumberOfArguments(aMethod) ; i++) { method_getArgumentInfo(aMethod, i, &type, &offset); strcat(array, decodeTypeForST(type)); strcat(array, " "); } strcat(array, ")"); return array; */ int i, offset, count, argCount = method_getNumberOfArguments(aMethod); const char *type; OOP array = (OOP)arrayNew(argCount); OOP argString; arrayAtPut(array, 1, symbolToOOP("cObject")); arrayAtPut(array, 2, symbolToOOP("cObject")); for (i=2 ; i < argCount ; i++) { method_getArgumentInfo(aMethod, i, &type, &offset); arrayAtPut(array, i+1, symbolToOOP(decodeTypeForST(type))); } return array; } // ============================================================ // Function: // Args: // Description: // ============================================================ SEL methodSelelector(Method aMethod) { return aMethod->method_name; } // ============================================================ // Function: // Args: // Description: // ============================================================ char *methodName(Method aMethod) { return (char *)sel_getName(aMethod->method_name); } // ============================================================ // Function: // Args: // Description: // ============================================================ int numberOfInstanceMethodsFor(id aClass) { struct objc_method_list *methods; SEL selector; int i; int total = 0; struct objc_class *s = (struct objc_object *)aClass; for (methods = s->methods; methods; methods = methods->method_next) for (i = 0; (i < methods->method_count); i++) if (!hasUnderscore(sel_getName((SEL)(methods->method_list[i].method_name)))) total++; return total; } // ============================================================ // Function: // Args: // Description: // ============================================================ Method instanceMethodFor(id aClass, int at) { struct objc_method_list *methods; SEL selector; //SEL *selectors; int i; int total = 0; struct objc_class *s = (struct objc_object *)aClass; for (methods = s->methods; methods; methods = methods->method_next) { for (i = 0; (i < methods->method_count); i++) { selector = (SEL)(methods->method_list[i].method_name); if (total == at && !hasUnderscore(sel_getName(selector))) return &(methods->method_list[i]); else if (!hasUnderscore(sel_getName(selector))) total++; } } return NULL; } // ============================================================ // Function: // Args: // Description: // ============================================================ int numberOfClassMethodsFor(id aClass) { struct objc_method_list *methods; int i; int total = 0; struct objc_class *s = (struct objc_object *)aClass; for (methods = s->isa->methods; methods; methods = methods->method_next) for (i = 0; (i < methods->method_count); i++) if (!hasUnderscore(sel_getName((SEL)(methods->method_list[i].method_name)))) total++; return total; } // ============================================================ // Function: // Args: // Description: // ============================================================ Method classMethodFor(id aClass, int at) { struct objc_method_list *methods; SEL selector; int i; int total = 0; struct objc_class *s = (struct objc_object *)aClass; for (methods = s->isa->methods; methods; methods = methods->method_next) { for (i = 0; (i < methods->method_count); i++) { selector = (SEL)(methods->method_list[i].method_name); if (total == at && !hasUnderscore(sel_getName(selector))) return &(methods->method_list[i]); else if (!hasUnderscore(sel_getName(selector))) total++; } } return NULL; } // ============================================================ // Function: // Args: // Description: // ============================================================ BOOL hasUnderscore(const char *string) { int i, len = strlen(string); for (i=0 ; i<len ; i++) if (string[i] == '_') return YES; return NO; } // ============================================================ // Function: // Args: // Description: // ============================================================ int numberOfSubclassesOf(id aClass) { NXHashTable *p; NXHashState state; void *value; int count = 0; struct objc_class *candidate; struct objc_class *of = (struct objc_object *)aClass; p = objc_getClasses(); state = NXInitHashState(p); while (NXNextHashState(p, &state, &value)) { candidate = (struct objc_class *) value; if (candidate->super_class == of) count++; } return count; } // ============================================================ // Function: // Args: // Description: // ============================================================ id subclassOf(id aClass, int at) { NXHashTable *p; NXHashState state; void *value; int count = 0; struct objc_class *candidate; struct objc_class *of = (struct objc_object *)aClass; id class; p = objc_getClasses(); state = NXInitHashState(p); while (NXNextHashState(p, &state, &value)) { candidate = (struct objc_class *) value; if (candidate->super_class == of) { if (at == count) return candidate; count++; } } return class; } // ============================================================ // Function: // Args: // Description: // ============================================================ int forwardToSmalltalk(id aClass, SEL aSelector) { return [[aClass class] forwardToSmalltalk:aSelector]; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.