Annotation of gcc/objc/class.c, revision 1.1.1.1

1.1       root        1: /* GNU Objective C Runtime class related functions
                      2:    Copyright (C) 1993 Free Software Foundation, Inc.
                      3: 
                      4: Author: Kresten Krab Thorup, Dennis Glatting
                      5: 
                      6: This file is part of GNU CC.
                      7: 
                      8: GNU CC is free software; you can redistribute it and/or modify it under the
                      9:    terms of the GNU General Public License as published by the Free Software
                     10:    Foundation; either version 2, or (at your option) any later version.
                     11: 
                     12: GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
                     13:    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
                     14:    FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
                     15:    details.
                     16: 
                     17: You should have received a copy of the GNU General Public License along with
                     18:    GNU CC; see the file COPYING.  If not, write to the Free Software
                     19:    Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     20: 
                     21: /* As a special exception, if you link this library with files compiled with
                     22:    GCC to produce an executable, this does not cause the resulting executable
                     23:    to be covered by the GNU General Public License. This exception does not
                     24:    however invalidate any other reasons why the executable file might be
                     25:    covered by the GNU General Public License.  */
                     26: 
                     27: #include "runtime.h"           /* the kitchen sink */
                     28: 
                     29: 
                     30: /* The table of classname->class.  Used for objc_lookup_class and friends */
                     31: static cache_ptr __objc_class_hash = 0;
                     32: 
                     33: /* This is a hook which is called by objc_get_class and 
                     34:    objc_lookup_class if the runtime is not able to find the class.
                     35:    This may e.g. try to load in the class using dynamic loading */
                     36: Class* (*_objc_lookup_class)(const char* name) = 0;
                     37: 
                     38: 
                     39: /* True when class links has been resolved */     
                     40: BOOL __objc_class_links_resolved = NO;
                     41: 
                     42: 
                     43: /* Initial number of buckets size of class hash table. */
                     44: #define CLASS_HASH_SIZE 32
                     45: 
                     46: void __objc_init_class_tables()
                     47: {
                     48:   /* Allocate the class hash table */
                     49: 
                     50:   if(__objc_class_hash)
                     51:     return;
                     52: 
                     53:   __objc_class_hash
                     54:     =  hash_new (CLASS_HASH_SIZE,
                     55:                 (hash_func_type) hash_string,
                     56:                 (compare_func_type) compare_strings);
                     57: }  
                     58: 
                     59: /* This function adds a class to the class hash table, and assigns the 
                     60:    class a number, unless it's already known */
                     61: void
                     62: __objc_add_class_to_hash(Class* class)
                     63: {
                     64:   Class* h_class;
                     65: 
                     66:   /* make sure the table is there */
                     67:   assert(__objc_class_hash);
                     68: 
                     69:   /* make sure it's not a meta class */  
                     70:   assert(CLS_ISCLASS(class));
                     71: 
                     72:   /* Check to see if the class is already in the hash table.  */
                     73:   h_class = hash_value_for_key (__objc_class_hash, class->name);
                     74:   if (!h_class)
                     75:     {
                     76:       /* The class isn't in the hash table.  Add the class and assign a class
                     77:          number.  */
                     78:       static unsigned int class_number = 1;
                     79: 
                     80:       CLS_SETNUMBER(class, class_number);
                     81:       CLS_SETNUMBER(class->class_pointer, class_number);
                     82: 
                     83:       ++class_number;
                     84:       hash_add (&__objc_class_hash, class->name, class);
                     85:     }
                     86: }
                     87: 
                     88: /* Get the class object for the class named NAME.  If NAME does not
                     89:    identify a known class, the hook _objc_lookup_class is called.  If
                     90:    this fails, nil is returned */
                     91: Class* objc_lookup_class (const char* name)
                     92: {
                     93:   Class* class;
                     94: 
                     95:   /* Make sure the class hash table exists.  */
                     96:   assert (__objc_class_hash);
                     97: 
                     98:   class = hash_value_for_key (__objc_class_hash, name);
                     99: 
                    100:   if (class)
                    101:     return class;
                    102: 
                    103:   if (_objc_lookup_class)
                    104:     return (*_objc_lookup_class)(name);
                    105:   else
                    106:     return 0;
                    107: }
                    108: 
                    109: /* Get the class object for the class named NAME.  If NAME does not
                    110:    identify a known class, the hook _objc_lookup_class is called.  If
                    111:    this fails,  an error message is issued and the system aborts */
                    112: Class*
                    113: objc_get_class (const char *name)
                    114: {
                    115:   Class* class;
                    116: 
                    117:   /* Make sure the class hash table exists.  */
                    118:   assert (__objc_class_hash);
                    119: 
                    120:   class = hash_value_for_key (__objc_class_hash, name);
                    121: 
                    122:   if (class)
                    123:     return class;
                    124: 
                    125:   if (_objc_lookup_class)
                    126:     class = (*_objc_lookup_class)(name);
                    127: 
                    128:   if(class)
                    129:     return class;
                    130:   
                    131:   fprintf(stderr, "objc runtime: cannot find class %s\n", name);
                    132:   abort();
                    133: }
                    134: 
                    135: 
                    136: /* Resolve super/subclass links for all classes.  The only thing we 
                    137:    can be sure of is that the class_pointer for class objects point 
                    138:    to the right meta class objects */
                    139: void __objc_resolve_class_links()
                    140: {
                    141:   node_ptr node;
                    142:   Class* object_class = objc_get_class ("Object");
                    143: 
                    144:   assert(object_class);
                    145: 
                    146:   /* Assign subclass links */
                    147:   for (node = hash_next (__objc_class_hash, NULL); node;
                    148:        node = hash_next (__objc_class_hash, node))
                    149:     {
                    150:       Class* class1 = node->value;
                    151: 
                    152:       /* Make sure we have what we think we have.  */
                    153:       assert (CLS_ISCLASS(class1));
                    154:       assert (CLS_ISMETA(class1->class_pointer));
                    155: 
                    156:       /* The class_pointer of all meta classes point to Object's meta class. */
                    157:       class1->class_pointer->class_pointer = object_class->class_pointer;
                    158: 
                    159:       if (!(CLS_ISRESOLV(class1)))
                    160:         {
                    161:           CLS_SETRESOLV(class1);
                    162:           CLS_SETRESOLV(class1->class_pointer);
                    163:               
                    164:           if(class1->super_class)
                    165:             {   
                    166:               Class* a_super_class 
                    167:                 = objc_get_class ((char *) class1->super_class);
                    168:               
                    169:               assert (a_super_class);
                    170:               
                    171:               DEBUG_PRINTF ("making class connections for: %s\n",
                    172:                             class1->name);
                    173:               
                    174:               /* assign subclass links for superclass */
                    175:               class1->sibling_class = a_super_class->subclass_list;
                    176:               a_super_class->subclass_list = class1;
                    177:               
                    178:               /* Assign subclass links for meta class of superclass */
                    179:               if (a_super_class->class_pointer)
                    180:                 {
                    181:                   class1->class_pointer->sibling_class
                    182:                     = a_super_class->class_pointer->subclass_list;
                    183:                   a_super_class->class_pointer->subclass_list 
                    184:                     = class1->class_pointer;
                    185:                 }
                    186:             }
                    187:           else                  /* a root class, make its meta object */
                    188:                                 /* be a subclass of Object */
                    189:             {
                    190:               class1->class_pointer->sibling_class 
                    191:                 = object_class->subclass_list;
                    192:               object_class->subclass_list = class1->class_pointer;
                    193:             }
                    194:         }
                    195:     }
                    196: 
                    197:   /* Assign superclass links */
                    198:   for (node = hash_next (__objc_class_hash, NULL); node;
                    199:        node = hash_next (__objc_class_hash, node))
                    200:     {
                    201:       Class* class1 = node->value;
                    202:       Class* sub_class;
                    203:       for (sub_class = class1->subclass_list; sub_class;
                    204:            sub_class = sub_class->sibling_class)
                    205:         {
                    206:           sub_class->super_class = class1;
                    207:           if(CLS_ISCLASS(sub_class))
                    208:             sub_class->class_pointer->super_class = class1->class_pointer;
                    209:         }
                    210:     }
                    211: }
                    212: 
                    213: 
                    214: /* This is a incomplete implementation of posing.   This function does the
                    215:    bulk of the work but does not initialize the class method caches.  That is
                    216:    a run-time specific operation.
                    217: 
                    218: I implement posing by hiding SUPER_CLASS, creating new class and meta class
                    219:    structures, initializing it with IMPOSTOR, and changing it such that it is
                    220:    identified as SUPER_CLASS. SUPER_CLASS remains in the hierarchy but is
                    221:    inaccessible by the means. The class hierarchy is then re arranged such
                    222:    that all of the subclasses of SUPER_CLASS now inherit from the new class
                    223:    structures -- except the impostor itself. The only dramatic effect on the
                    224:    application is that subclasses of SUPER_CLASS cannot do a [ ....
                    225:    super_class ] and expect their real super class. */
                    226: Class*
                    227: class_pose_as (Class* impostor, Class* super_class)
                    228: {
                    229:   Class* new_class = (Class*) __objc_xcalloc (1, sizeof (Class));
                    230:   MetaClass* new_meta_class =
                    231:     (MetaClass*) __objc_xmalloc(sizeof (MetaClass));
                    232:   char *new_name = (char *)__objc_xmalloc ((size_t)strlen ((char*)super_class->name) + 12);
                    233: 
                    234:   /* We must know the state of the hierachy.  Do initial setup if needed */
                    235:   if(!CLS_ISRESOLV(impostor))
                    236:     __objc_resolve_class_links();
                    237: 
                    238:   assert (new_class);
                    239:   assert (new_meta_class);
                    240:   assert (new_name);
                    241: 
                    242:   assert (CLS_ISCLASS(impostor));
                    243:   assert (CLS_ISCLASS(super_class));
                    244: 
                    245:   assert (impostor->instance_size == super_class->instance_size);
                    246: 
                    247:   /* Create the impostor class.  */
                    248:   new_class->class_pointer = new_meta_class;
                    249:   new_class->super_class = super_class;
                    250:   new_class->name = super_class->name;
                    251:   new_class->version = super_class->version;
                    252:   new_class->info = super_class->info;
                    253:   new_class->instance_size = super_class->instance_size;
                    254:   new_class->ivars = super_class->ivars;
                    255:   new_class->methods = impostor->methods;
                    256:   new_class->dtable = impostor->dtable;
                    257: 
                    258:   /* Create the impostor meta class.  */
                    259:   new_meta_class->class_pointer = super_class->class_pointer->class_pointer;
                    260:   new_meta_class->super_class = super_class->class_pointer->super_class;
                    261:   new_meta_class->name = super_class->class_pointer->name;
                    262:   new_meta_class->version = super_class->class_pointer->version;
                    263:   new_meta_class->info = super_class->class_pointer->info;
                    264:   new_meta_class->instance_size = super_class->class_pointer->instance_size;
                    265:   new_meta_class->ivars = super_class->class_pointer->ivars;
                    266:   new_meta_class->methods = impostor->class_pointer->methods;
                    267:   new_meta_class->dtable = impostor->class_pointer->dtable;
                    268: 
                    269:   /* Now change super/subclass links of all related classes.  This is rather
                    270:      complex, since we have both super_class link, and subclass_list for the
                    271:      involved classes. */
                    272:   {
                    273:     Class* *classpp;
                    274:     MetaClass* *metaclasspp;
                    275: 
                    276:     /* Remove impostor from subclass list of super_class */
                    277:     for (classpp = &(super_class->subclass_list);
                    278:          *classpp;
                    279:          classpp = &((*classpp)->sibling_class))
                    280:       {
                    281:         if (*classpp == impostor)
                    282:           *classpp = (*classpp)->sibling_class;
                    283:         if (*classpp == 0)
                    284:           break;
                    285:       }
                    286: 
                    287:     /* Do the same for the meta classes */
                    288: 
                    289:     for (metaclasspp = &(super_class->class_pointer->subclass_list);
                    290:          *metaclasspp;
                    291:          metaclasspp = &((*metaclasspp)->sibling_class))
                    292:       {
                    293:         if (*metaclasspp == impostor->class_pointer)
                    294:           *metaclasspp = (*metaclasspp)->sibling_class;
                    295:         if (*metaclasspp == 0)
                    296:           break;
                    297:       }
                    298: 
                    299:     /* From the loop above, classpp now points to the sibling_class entry */
                    300:     /* of the last element in the list of subclasses for super_class */
                    301: 
                    302:     /* Append the subclass list of impostor to the subclass list of */
                    303:     /* superclass, and excange those two and set subclass of */
                    304:     /* super_class to be impostor only */
                    305: 
                    306:     *classpp = impostor->subclass_list;
                    307:     new_class->subclass_list = super_class->subclass_list;
                    308:     super_class->subclass_list = new_class;
                    309:     new_class->sibling_class = 0;
                    310: 
                    311:     /* Do the same thing for the meta classes */
                    312:     *metaclasspp = impostor->class_pointer->subclass_list;
                    313:     new_meta_class->subclass_list = super_class->class_pointer->subclass_list;
                    314:     super_class->class_pointer->subclass_list = new_meta_class;
                    315:     new_meta_class->sibling_class = 0;
                    316: 
                    317:     /* Update superclass links for all subclasses of new_class */
                    318:     for (classpp = &(new_class->subclass_list); *classpp;
                    319:          classpp = &((*classpp)->sibling_class))
                    320:       (*classpp)->super_class = new_class;
                    321: 
                    322:     for (metaclasspp = &(new_meta_class->subclass_list); *metaclasspp;
                    323:          metaclasspp = &((*metaclasspp)->sibling_class))
                    324:       (*metaclasspp)->super_class = new_meta_class;
                    325: 
                    326:   }
                    327: 
                    328:   /* Delete the class from the hash table, change its name so that it can no
                    329:      longer be found, then place it back into the hash table using its new
                    330:      name.
                    331:   
                    332:   Don't worry about the class number.  It is already assigned.
                    333:      memory is lost with the hash key.) */
                    334:   hash_remove (__objc_class_hash, super_class->name);
                    335:   sprintf (new_name, "%s*", super_class->name);
                    336:   super_class->name = new_name;
                    337:   super_class->class_pointer->name = new_name;
                    338:   hash_add (&__objc_class_hash, super_class->name, super_class);
                    339: 
                    340:   /* Place the impostor class in class hash table and assign it a class
                    341:      number.  */
                    342:   __objc_add_class_to_hash (new_class);
                    343: 
                    344:   /* Now update dispatch tables for new_class and it's subclasses */
                    345:   __objc_update_dispatch_table_for_class ((Class*) new_meta_class);
                    346:   __objc_update_dispatch_table_for_class (new_class);
                    347: 
                    348:   return new_class;
                    349: }
                    350: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.