--- gcc/objc/class.c 2018/04/24 18:10:15 1.1 +++ gcc/objc/class.c 2018/04/24 18:26:46 1.1.1.4 @@ -1,22 +1,21 @@ /* GNU Objective C Runtime class related functions - Copyright (C) 1993 Free Software Foundation, Inc. - -Author: Kresten Krab Thorup, Dennis Glatting + Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Contributed by Kresten Krab Thorup and Dennis Glatting. This file is part of GNU CC. GNU CC is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 2, or (at your option) any later version. +terms of the GNU General Public License as published by the Free Software +Foundation; either version 2, or (at your option) any later version. GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - details. +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. You should have received a copy of the GNU General Public License along with - GNU CC; see the file COPYING. If not, write to the Free Software - Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +GNU CC; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, if you link this library with files compiled with GCC to produce an executable, this does not cause the resulting executable @@ -25,7 +24,7 @@ You should have received a copy of the G covered by the GNU General Public License. */ #include "runtime.h" /* the kitchen sink */ - +#include "sarray.h" /* The table of classname->class. Used for objc_lookup_class and friends */ static cache_ptr __objc_class_hash = 0; @@ -33,7 +32,7 @@ static cache_ptr __objc_class_hash = 0; /* This is a hook which is called by objc_get_class and objc_lookup_class if the runtime is not able to find the class. This may e.g. try to load in the class using dynamic loading */ -Class* (*_objc_lookup_class)(const char* name) = 0; +Class (*_objc_lookup_class)(const char* name) = 0; /* True when class links has been resolved */ @@ -59,9 +58,9 @@ void __objc_init_class_tables() /* This function adds a class to the class hash table, and assigns the class a number, unless it's already known */ void -__objc_add_class_to_hash(Class* class) +__objc_add_class_to_hash(Class class) { - Class* h_class; + Class h_class; /* make sure the table is there */ assert(__objc_class_hash); @@ -88,9 +87,9 @@ __objc_add_class_to_hash(Class* class) /* Get the class object for the class named NAME. If NAME does not identify a known class, the hook _objc_lookup_class is called. If this fails, nil is returned */ -Class* objc_lookup_class (const char* name) +Class objc_lookup_class (const char* name) { - Class* class; + Class class; /* Make sure the class hash table exists. */ assert (__objc_class_hash); @@ -109,10 +108,10 @@ Class* objc_lookup_class (const char* na /* Get the class object for the class named NAME. If NAME does not identify a known class, the hook _objc_lookup_class is called. If this fails, an error message is issued and the system aborts */ -Class* +Class objc_get_class (const char *name) { - Class* class; + Class class; /* Make sure the class hash table exists. */ assert (__objc_class_hash); @@ -132,6 +131,33 @@ objc_get_class (const char *name) abort(); } +MetaClass +objc_get_meta_class(const char *name) +{ + return objc_get_class(name)->class_pointer; +} + +/* This function provides a way to enumerate all the classes in the + executable. Pass *ENUM_STATE == NULL to start the enumeration. The + function will return 0 when there are no more classes. + For example: + id class; + void *es = NULL; + while ((class = objc_next_class(&es))) + ... do something with class; +*/ +Class +objc_next_class(void **enum_state) +{ + /* make sure the table is there */ + assert(__objc_class_hash); + + *(node_ptr*)enum_state = + hash_next(__objc_class_hash, *(node_ptr*)enum_state); + if (*(node_ptr*)enum_state) + return (*(node_ptr*)enum_state)->value; + return (Class)0; +} /* Resolve super/subclass links for all classes. The only thing we can be sure of is that the class_pointer for class objects point @@ -139,7 +165,7 @@ objc_get_class (const char *name) void __objc_resolve_class_links() { node_ptr node; - Class* object_class = objc_get_class ("Object"); + Class object_class = objc_get_class ("Object"); assert(object_class); @@ -147,7 +173,7 @@ void __objc_resolve_class_links() for (node = hash_next (__objc_class_hash, NULL); node; node = hash_next (__objc_class_hash, node)) { - Class* class1 = node->value; + Class class1 = node->value; /* Make sure we have what we think we have. */ assert (CLS_ISCLASS(class1)); @@ -163,7 +189,7 @@ void __objc_resolve_class_links() if(class1->super_class) { - Class* a_super_class + Class a_super_class = objc_get_class ((char *) class1->super_class); assert (a_super_class); @@ -198,8 +224,8 @@ void __objc_resolve_class_links() for (node = hash_next (__objc_class_hash, NULL); node; node = hash_next (__objc_class_hash, node)) { - Class* class1 = node->value; - Class* sub_class; + Class class1 = node->value; + Class sub_class; for (sub_class = class1->subclass_list; sub_class; sub_class = sub_class->sibling_class) { @@ -211,140 +237,91 @@ void __objc_resolve_class_links() } -/* This is a incomplete implementation of posing. This function does the - bulk of the work but does not initialize the class method caches. That is - a run-time specific operation. - -I implement posing by hiding SUPER_CLASS, creating new class and meta class - structures, initializing it with IMPOSTOR, and changing it such that it is - identified as SUPER_CLASS. SUPER_CLASS remains in the hierarchy but is - inaccessible by the means. The class hierarchy is then re arranged such - that all of the subclasses of SUPER_CLASS now inherit from the new class - structures -- except the impostor itself. The only dramatic effect on the - application is that subclasses of SUPER_CLASS cannot do a [ .... - super_class ] and expect their real super class. */ -Class* -class_pose_as (Class* impostor, Class* super_class) + +#define CLASSOF(c) ((c)->class_pointer) + +Class +class_pose_as (Class impostor, Class super_class) { - Class* new_class = (Class*) __objc_xcalloc (1, sizeof (Class)); - MetaClass* new_meta_class = - (MetaClass*) __objc_xmalloc(sizeof (MetaClass)); - char *new_name = (char *)__objc_xmalloc ((size_t)strlen ((char*)super_class->name) + 12); - - /* We must know the state of the hierachy. Do initial setup if needed */ - if(!CLS_ISRESOLV(impostor)) - __objc_resolve_class_links(); - - assert (new_class); - assert (new_meta_class); - assert (new_name); + node_ptr node; + Class class1; - assert (CLS_ISCLASS(impostor)); - assert (CLS_ISCLASS(super_class)); + if (!CLS_ISRESOLV (impostor)) + __objc_resolve_class_links (); + /* preconditions */ + assert (impostor); + assert (super_class); + assert (impostor->super_class == super_class); + assert (CLS_ISCLASS (impostor)); + assert (CLS_ISCLASS (super_class)); assert (impostor->instance_size == super_class->instance_size); - /* Create the impostor class. */ - new_class->class_pointer = new_meta_class; - new_class->super_class = super_class; - new_class->name = super_class->name; - new_class->version = super_class->version; - new_class->info = super_class->info; - new_class->instance_size = super_class->instance_size; - new_class->ivars = super_class->ivars; - new_class->methods = impostor->methods; - new_class->dtable = impostor->dtable; - - /* Create the impostor meta class. */ - new_meta_class->class_pointer = super_class->class_pointer->class_pointer; - new_meta_class->super_class = super_class->class_pointer->super_class; - new_meta_class->name = super_class->class_pointer->name; - new_meta_class->version = super_class->class_pointer->version; - new_meta_class->info = super_class->class_pointer->info; - new_meta_class->instance_size = super_class->class_pointer->instance_size; - new_meta_class->ivars = super_class->class_pointer->ivars; - new_meta_class->methods = impostor->class_pointer->methods; - new_meta_class->dtable = impostor->class_pointer->dtable; - - /* Now change super/subclass links of all related classes. This is rather - complex, since we have both super_class link, and subclass_list for the - involved classes. */ { - Class* *classpp; - MetaClass* *metaclasspp; + Class *subclass = &(super_class->subclass_list); - /* Remove impostor from subclass list of super_class */ - for (classpp = &(super_class->subclass_list); - *classpp; - classpp = &((*classpp)->sibling_class)) + /* move subclasses of super_class to impostor */ + while (*subclass) { - if (*classpp == impostor) - *classpp = (*classpp)->sibling_class; - if (*classpp == 0) - break; - } + Class nextSub = (*subclass)->sibling_class; - /* Do the same for the meta classes */ + if (*subclass != impostor) + { + Class sub = *subclass; + + /* classes */ + sub->sibling_class = impostor->subclass_list; + sub->super_class = impostor; + impostor->subclass_list = sub; + + /* It will happen that SUB is not a class object if it is + the top of the meta class hierarchy chain. (root + meta-class objects inherit their class object) If that is + the case... don't mess with the meta-meta class. */ + if (CLS_ISCLASS (sub)) + { + /* meta classes */ + CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list; + CLASSOF (sub)->super_class = CLASSOF (impostor); + CLASSOF (impostor)->subclass_list = CLASSOF (sub); + } + } - for (metaclasspp = &(super_class->class_pointer->subclass_list); - *metaclasspp; - metaclasspp = &((*metaclasspp)->sibling_class)) - { - if (*metaclasspp == impostor->class_pointer) - *metaclasspp = (*metaclasspp)->sibling_class; - if (*metaclasspp == 0) - break; + *subclass = nextSub; } - /* From the loop above, classpp now points to the sibling_class entry */ - /* of the last element in the list of subclasses for super_class */ - - /* Append the subclass list of impostor to the subclass list of */ - /* superclass, and excange those two and set subclass of */ - /* super_class to be impostor only */ - - *classpp = impostor->subclass_list; - new_class->subclass_list = super_class->subclass_list; - super_class->subclass_list = new_class; - new_class->sibling_class = 0; - - /* Do the same thing for the meta classes */ - *metaclasspp = impostor->class_pointer->subclass_list; - new_meta_class->subclass_list = super_class->class_pointer->subclass_list; - super_class->class_pointer->subclass_list = new_meta_class; - new_meta_class->sibling_class = 0; - - /* Update superclass links for all subclasses of new_class */ - for (classpp = &(new_class->subclass_list); *classpp; - classpp = &((*classpp)->sibling_class)) - (*classpp)->super_class = new_class; - - for (metaclasspp = &(new_meta_class->subclass_list); *metaclasspp; - metaclasspp = &((*metaclasspp)->sibling_class)) - (*metaclasspp)->super_class = new_meta_class; - + /* set subclasses of superclass to be impostor only */ + super_class->subclass_list = impostor; + CLASSOF (super_class)->subclass_list = CLASSOF (impostor); + + /* set impostor to have no sibling classes */ + impostor->sibling_class = 0; + CLASSOF (impostor)->sibling_class = 0; } - - /* Delete the class from the hash table, change its name so that it can no - longer be found, then place it back into the hash table using its new - name. - Don't worry about the class number. It is already assigned. - memory is lost with the hash key.) */ - hash_remove (__objc_class_hash, super_class->name); - sprintf (new_name, "%s*", super_class->name); - super_class->name = new_name; - super_class->class_pointer->name = new_name; - hash_add (&__objc_class_hash, super_class->name, super_class); - - /* Place the impostor class in class hash table and assign it a class - number. */ - __objc_add_class_to_hash (new_class); - - /* Now update dispatch tables for new_class and it's subclasses */ - __objc_update_dispatch_table_for_class ((Class*) new_meta_class); - __objc_update_dispatch_table_for_class (new_class); + /* check relationship of impostor and super_class is kept. */ + assert (impostor->super_class == super_class); + assert (CLASSOF (impostor)->super_class == CLASSOF (super_class)); + + /* This is how to update the lookup table. Regardless of + what the keys of the hashtable is, change all values that are + superclass into impostor. */ - return new_class; + for (node = hash_next (__objc_class_hash, NULL); node; + node = hash_next (__objc_class_hash, node)) + { + class1 = (Class)node->value; + if (class1 == super_class) + { + node->value = impostor; /* change hash table value */ + } + } + + /* next, we update the dispatch tables... */ + __objc_update_dispatch_table_for_class (CLASSOF (impostor)); + __objc_update_dispatch_table_for_class (impostor); + + return impostor; } +