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.