Annotation of gcc/objc/class.c, revision 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.