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

1.1       root        1: /* GNU Objective C Runtime class related functions
1.1.1.4 ! root        2:    Copyright (C) 1993, 1995 Free Software Foundation, Inc.
        !             3:    Contributed by Kresten Krab Thorup and Dennis Glatting.
1.1       root        4: 
                      5: This file is part of GNU CC.
                      6: 
                      7: GNU CC is free software; you can redistribute it and/or modify it under the
1.1.1.4 ! root        8: terms of the GNU General Public License as published by the Free Software
        !             9: Foundation; either version 2, or (at your option) any later version.
1.1       root       10: 
                     11: GNU CC is distributed in the hope that it will be useful, but WITHOUT ANY
1.1.1.4 ! root       12: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
        !            13: FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
        !            14: details.
1.1       root       15: 
                     16: You should have received a copy of the GNU General Public License along with
1.1.1.4 ! root       17: GNU CC; see the file COPYING.  If not, write to the Free Software
        !            18: Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
1.1       root       19: 
                     20: /* As a special exception, if you link this library with files compiled with
                     21:    GCC to produce an executable, this does not cause the resulting executable
                     22:    to be covered by the GNU General Public License. This exception does not
                     23:    however invalidate any other reasons why the executable file might be
                     24:    covered by the GNU General Public License.  */
                     25: 
                     26: #include "runtime.h"           /* the kitchen sink */
1.1.1.2   root       27: #include "sarray.h"
1.1       root       28: 
                     29: /* The table of classname->class.  Used for objc_lookup_class and friends */
                     30: static cache_ptr __objc_class_hash = 0;
                     31: 
                     32: /* This is a hook which is called by objc_get_class and 
                     33:    objc_lookup_class if the runtime is not able to find the class.
                     34:    This may e.g. try to load in the class using dynamic loading */
1.1.1.4 ! root       35: Class (*_objc_lookup_class)(const char* name) = 0;
1.1       root       36: 
                     37: 
                     38: /* True when class links has been resolved */     
                     39: BOOL __objc_class_links_resolved = NO;
                     40: 
                     41: 
                     42: /* Initial number of buckets size of class hash table. */
                     43: #define CLASS_HASH_SIZE 32
                     44: 
                     45: void __objc_init_class_tables()
                     46: {
                     47:   /* Allocate the class hash table */
                     48: 
                     49:   if(__objc_class_hash)
                     50:     return;
                     51: 
                     52:   __objc_class_hash
                     53:     =  hash_new (CLASS_HASH_SIZE,
                     54:                 (hash_func_type) hash_string,
                     55:                 (compare_func_type) compare_strings);
                     56: }  
                     57: 
                     58: /* This function adds a class to the class hash table, and assigns the 
                     59:    class a number, unless it's already known */
                     60: void
1.1.1.4 ! root       61: __objc_add_class_to_hash(Class class)
1.1       root       62: {
1.1.1.4 ! root       63:   Class h_class;
1.1       root       64: 
                     65:   /* make sure the table is there */
                     66:   assert(__objc_class_hash);
                     67: 
                     68:   /* make sure it's not a meta class */  
                     69:   assert(CLS_ISCLASS(class));
                     70: 
                     71:   /* Check to see if the class is already in the hash table.  */
                     72:   h_class = hash_value_for_key (__objc_class_hash, class->name);
                     73:   if (!h_class)
                     74:     {
                     75:       /* The class isn't in the hash table.  Add the class and assign a class
                     76:          number.  */
                     77:       static unsigned int class_number = 1;
                     78: 
                     79:       CLS_SETNUMBER(class, class_number);
                     80:       CLS_SETNUMBER(class->class_pointer, class_number);
                     81: 
                     82:       ++class_number;
                     83:       hash_add (&__objc_class_hash, class->name, class);
                     84:     }
                     85: }
                     86: 
                     87: /* Get the class object for the class named NAME.  If NAME does not
                     88:    identify a known class, the hook _objc_lookup_class is called.  If
                     89:    this fails, nil is returned */
1.1.1.4 ! root       90: Class objc_lookup_class (const char* name)
1.1       root       91: {
1.1.1.4 ! root       92:   Class class;
1.1       root       93: 
                     94:   /* Make sure the class hash table exists.  */
                     95:   assert (__objc_class_hash);
                     96: 
                     97:   class = hash_value_for_key (__objc_class_hash, name);
                     98: 
                     99:   if (class)
                    100:     return class;
                    101: 
                    102:   if (_objc_lookup_class)
                    103:     return (*_objc_lookup_class)(name);
                    104:   else
                    105:     return 0;
                    106: }
                    107: 
                    108: /* Get the class object for the class named NAME.  If NAME does not
                    109:    identify a known class, the hook _objc_lookup_class is called.  If
                    110:    this fails,  an error message is issued and the system aborts */
1.1.1.4 ! root      111: Class
1.1       root      112: objc_get_class (const char *name)
                    113: {
1.1.1.4 ! root      114:   Class class;
1.1       root      115: 
                    116:   /* Make sure the class hash table exists.  */
                    117:   assert (__objc_class_hash);
                    118: 
                    119:   class = hash_value_for_key (__objc_class_hash, name);
                    120: 
                    121:   if (class)
                    122:     return class;
                    123: 
                    124:   if (_objc_lookup_class)
                    125:     class = (*_objc_lookup_class)(name);
                    126: 
                    127:   if(class)
                    128:     return class;
                    129:   
                    130:   fprintf(stderr, "objc runtime: cannot find class %s\n", name);
                    131:   abort();
                    132: }
                    133: 
1.1.1.4 ! root      134: MetaClass
1.1.1.3   root      135: objc_get_meta_class(const char *name)
                    136: {
                    137:   return objc_get_class(name)->class_pointer;
                    138: }
                    139: 
                    140: /* This function provides a way to enumerate all the classes in the
                    141:    executable.  Pass *ENUM_STATE == NULL to start the enumeration.  The
                    142:    function will return 0 when there are no more classes.  
                    143:    For example: 
                    144:        id class; 
                    145:        void *es = NULL;
                    146:        while ((class = objc_next_class(&es)))
                    147:          ... do something with class; 
                    148: */
1.1.1.4 ! root      149: Class
1.1.1.3   root      150: objc_next_class(void **enum_state)
                    151: {
                    152:   /* make sure the table is there */
                    153:   assert(__objc_class_hash);
                    154: 
                    155:   *(node_ptr*)enum_state = 
                    156:     hash_next(__objc_class_hash, *(node_ptr*)enum_state);
                    157:   if (*(node_ptr*)enum_state)
                    158:     return (*(node_ptr*)enum_state)->value;
1.1.1.4 ! root      159:   return (Class)0;
1.1.1.3   root      160: }
1.1       root      161: 
                    162: /* Resolve super/subclass links for all classes.  The only thing we 
                    163:    can be sure of is that the class_pointer for class objects point 
                    164:    to the right meta class objects */
                    165: void __objc_resolve_class_links()
                    166: {
                    167:   node_ptr node;
1.1.1.4 ! root      168:   Class object_class = objc_get_class ("Object");
1.1       root      169: 
                    170:   assert(object_class);
                    171: 
                    172:   /* Assign subclass links */
                    173:   for (node = hash_next (__objc_class_hash, NULL); node;
                    174:        node = hash_next (__objc_class_hash, node))
                    175:     {
1.1.1.4 ! root      176:       Class class1 = node->value;
1.1       root      177: 
                    178:       /* Make sure we have what we think we have.  */
                    179:       assert (CLS_ISCLASS(class1));
                    180:       assert (CLS_ISMETA(class1->class_pointer));
                    181: 
                    182:       /* The class_pointer of all meta classes point to Object's meta class. */
                    183:       class1->class_pointer->class_pointer = object_class->class_pointer;
                    184: 
                    185:       if (!(CLS_ISRESOLV(class1)))
                    186:         {
                    187:           CLS_SETRESOLV(class1);
                    188:           CLS_SETRESOLV(class1->class_pointer);
                    189:               
                    190:           if(class1->super_class)
                    191:             {   
1.1.1.4 ! root      192:               Class a_super_class 
1.1       root      193:                 = objc_get_class ((char *) class1->super_class);
                    194:               
                    195:               assert (a_super_class);
                    196:               
                    197:               DEBUG_PRINTF ("making class connections for: %s\n",
                    198:                             class1->name);
                    199:               
                    200:               /* assign subclass links for superclass */
                    201:               class1->sibling_class = a_super_class->subclass_list;
                    202:               a_super_class->subclass_list = class1;
                    203:               
                    204:               /* Assign subclass links for meta class of superclass */
                    205:               if (a_super_class->class_pointer)
                    206:                 {
                    207:                   class1->class_pointer->sibling_class
                    208:                     = a_super_class->class_pointer->subclass_list;
                    209:                   a_super_class->class_pointer->subclass_list 
                    210:                     = class1->class_pointer;
                    211:                 }
                    212:             }
                    213:           else                  /* a root class, make its meta object */
                    214:                                 /* be a subclass of Object */
                    215:             {
                    216:               class1->class_pointer->sibling_class 
                    217:                 = object_class->subclass_list;
                    218:               object_class->subclass_list = class1->class_pointer;
                    219:             }
                    220:         }
                    221:     }
                    222: 
                    223:   /* Assign superclass links */
                    224:   for (node = hash_next (__objc_class_hash, NULL); node;
                    225:        node = hash_next (__objc_class_hash, node))
                    226:     {
1.1.1.4 ! root      227:       Class class1 = node->value;
        !           228:       Class sub_class;
1.1       root      229:       for (sub_class = class1->subclass_list; sub_class;
                    230:            sub_class = sub_class->sibling_class)
                    231:         {
                    232:           sub_class->super_class = class1;
                    233:           if(CLS_ISCLASS(sub_class))
                    234:             sub_class->class_pointer->super_class = class1->class_pointer;
                    235:         }
                    236:     }
                    237: }
                    238: 
                    239: 
1.1.1.2   root      240: 
                    241: #define CLASSOF(c) ((c)->class_pointer)
                    242: 
1.1.1.4 ! root      243: Class
        !           244: class_pose_as (Class impostor, Class super_class)
1.1       root      245: {
1.1.1.3   root      246:   node_ptr node;
1.1.1.4 ! root      247:   Class class1;
1.1.1.3   root      248: 
1.1.1.2   root      249:   if (!CLS_ISRESOLV (impostor))
                    250:     __objc_resolve_class_links ();
1.1       root      251: 
1.1.1.2   root      252:   /* preconditions */
                    253:   assert (impostor);
                    254:   assert (super_class);
                    255:   assert (impostor->super_class == super_class);
                    256:   assert (CLS_ISCLASS (impostor));
                    257:   assert (CLS_ISCLASS (super_class));
1.1       root      258:   assert (impostor->instance_size == super_class->instance_size);
                    259: 
                    260:   {
1.1.1.4 ! root      261:     Class *subclass = &(super_class->subclass_list);
1.1       root      262: 
1.1.1.2   root      263:     /* move subclasses of super_class to impostor */
                    264:     while (*subclass)
1.1       root      265:       {
1.1.1.4 ! root      266:        Class nextSub = (*subclass)->sibling_class;
1.1.1.2   root      267: 
1.1.1.3   root      268:        if (*subclass != impostor)
1.1.1.2   root      269:          {
1.1.1.4 ! root      270:            Class sub = *subclass;
1.1.1.2   root      271: 
                    272:            /* classes */
                    273:            sub->sibling_class = impostor->subclass_list;
                    274:            sub->super_class = impostor;
                    275:            impostor->subclass_list = sub;
1.1.1.3   root      276: 
                    277:            /* It will happen that SUB is not a class object if it is 
1.1.1.4 ! root      278:               the top of the meta class hierarchy chain.  (root
        !           279:               meta-class objects inherit their class object)  If that is
        !           280:               the case... don't mess with the meta-meta class. */ 
1.1.1.3   root      281:            if (CLS_ISCLASS (sub))
                    282:              {
                    283:                /* meta classes */
                    284:                CLASSOF (sub)->sibling_class = CLASSOF (impostor)->subclass_list;
                    285:                CLASSOF (sub)->super_class = CLASSOF (impostor);
                    286:                CLASSOF (impostor)->subclass_list = CLASSOF (sub);
                    287:              }
1.1.1.2   root      288:          }
                    289: 
                    290:        *subclass = nextSub;
1.1       root      291:       }
                    292: 
1.1.1.2   root      293:     /* set subclasses of superclass to be impostor only */
                    294:     super_class->subclass_list = impostor;
                    295:     CLASSOF (super_class)->subclass_list = CLASSOF (impostor);
                    296:     
                    297:     /* set impostor to have no sibling classes */
                    298:     impostor->sibling_class = 0;
                    299:     CLASSOF (impostor)->sibling_class = 0;
                    300:   }
                    301:   
1.1.1.3   root      302:   /* check relationship of impostor and super_class is kept. */
1.1.1.2   root      303:   assert (impostor->super_class == super_class);
                    304:   assert (CLASSOF (impostor)->super_class == CLASSOF (super_class));
                    305: 
1.1.1.3   root      306:   /* This is how to update the lookup table. Regardless of
                    307:      what the keys of the hashtable is, change all values that are
1.1.1.4 ! root      308:      superclass into impostor. */
1.1.1.2   root      309: 
1.1.1.3   root      310:   for (node = hash_next (__objc_class_hash, NULL); node;
                    311:        node = hash_next (__objc_class_hash, node))
                    312:     {
1.1.1.4 ! root      313:       class1 = (Class)node->value;
1.1.1.3   root      314:       if (class1 == super_class)
                    315:        {
                    316:          node->value = impostor; /* change hash table value */
                    317:        }
                    318:     }      
1.1       root      319: 
1.1.1.2   root      320:   /* next, we update the dispatch tables... */
1.1.1.3   root      321:   __objc_update_dispatch_table_for_class (CLASSOF (impostor));
                    322:   __objc_update_dispatch_table_for_class (impostor);
1.1.1.2   root      323: 
                    324:   return impostor;
                    325: }
                    326:   
1.1.1.3   root      327: 

unix.superglobalmegacorp.com

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