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

1.1       root        1: /* Method dispatcher and class-object creator for Objective C.
                      2:    Copyright (C) 1992 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: /* As a special exception, if you link this library with files
                     21:    compiled with GCC to produce an executable, this does not cause
                     22:    the resulting executable to be covered by the GNU General Public License.
                     23:    This exception does not however invalidate any other reasons why
                     24:    the executable file might be covered by the GNU General Public License.  */
                     25: 
                     26: #include "tconfig.h"
                     27: #include "assert.h"
                     28: #include <ctype.h>
                     29: #include "gstdarg.h"
                     30: #include <stdio.h>
                     31: #include "gstddef.h"
                     32: 
                     33: #include "hash.h"
                     34: #include "objc.h"
                     35: #include "objc-proto.h"
                     36: 
                     37: 
                     38: #define MODULE_HASH_SIZE 32   /* Initial module hash table size.
                     39:                                 Value doesn't really matter.  */
                     40: 
                     41: #define CLASS_HASH_SIZE 32    /* Initial number of buckets size of
                     42:                                 class hash table.  Value doesn't
                     43:                                 really matter.  */
                     44: 
                     45: 
                     46: /* Forward declare some functions.  */
                     47: id            objc_object_create (Class_t),
                     48:               objc_object_dispose (id),
                     49:               objc_object_realloc (id, unsigned int),
                     50:               objc_object_copy (id);
                     51: void          objc_error (id object, const char *fmt, va_list ap);
                     52: static id     nil_method (id, SEL, ...);
                     53: static id     return_error_static (id, SEL, ...);
                     54: static IMP    handle_runtime_error (id, SEL);
                     55: static void   initialize_dispatch_tables (void);
                     56: static SEL    record_selector (const char*);
                     57: static void   record_methods_from_class (Class_t);
                     58: static void   record_methods_from_list (MethodList_t);
                     59: static void   initialize_class (const char*);
                     60: /*
                     61:  * This is a hash table of Class_t structures. 
                     62:  *
                     63:  * At initialization the executable is searched for all Class_t structures. 
                     64:  * Since these structures are created by the compiler they are therefore
                     65:  * located in the TEXT segment.  
                     66:  *
                     67:  * A identical structure is allocated from the free store and initialized from
                     68:  * its TEXT counterpart and placed in the hash table using the TEXT part as
                     69:  * its key. 
                     70:  *
                     71:  * Since the free store structure is now writable, additional initialization
                     72:  * takes place such as its "info" variable, method cache allocation, and
                     73:  * linking of all of its method and ivar lists from multiple implementations. 
                     74:  */
                     75: cache_ptr      class_hash_table = NULL;
                     76: 
                     77: /*
                     78:  * This variable is a flag used within the messaging routines.  If a
                     79:  * application sets it to !0 then the messager will print messages sent to
                     80:  * objects. 
                     81:  */
                     82: BOOL  objc_trace = NO;
                     83: 
                     84: /* This mutex provides a course lock for method dispatch.  */
                     85: MUTEX  runtimeMutex;
                     86: 
                     87: /*
                     88:  * This hash table is used by the initialization routines.  When the
                     89:  * constructor function (__objc_execClass) is called it is passed a pointer
                     90:  * to a module structure.  That pointer is stored in this table and its
                     91:  * contents are processed in __objcInit. 
                     92:  */
                     93: cache_ptr    module_hash_table = NULL;
                     94: 
                     95: /*
                     96:  * This hash table is used in the constructor subroutine to hold pointers 
                     97:  * to categories that have not been attached to a class.  Constructors are
                     98:  * received in a random order.  Files may contain category implementation
                     99:  * of objects whose constructor hasn't been executed yet.  Therefore, 
                    100:  * there is no object to attach the categories.
                    101:  *
                    102:  * This hash table holds pointers to categories that haven't been
                    103:  * attached to objects.  As objects are processed the category hash
                    104:  * table is searched for attachments.  If a category is found for the
                    105:  * object it is attached to the object and deleted from the hash table.
                    106:  */
                    107: cache_ptr    unclaimed_category_hash_table = NULL;
                    108: 
                    109: /*
                    110:  * This flag is used by the messager routines to determine if the run-time
                    111:  * has been initialized.  If the run-time isn't initialized then a
                    112:  * initialization clean up routine is called. 
                    113:  */
                    114: static int     initialized = 0;
                    115: 
                    116: /*
                    117:  * Records that hold pointers to arrays of records.  The terminal records are
                    118:  * method implementations. 
                    119:  *
                    120:  * The size of the first record is the number of unique classes in the
                    121:  * executable.  The second is the number of selectors. 
                    122:  *
                    123:  * The second record conatins methods that are visible to the class -- that is,
                    124:  * methods that are not overriden from the classt to the root object. 
                    125:  *
                    126:  * The cache pointers of class and meta class structures point to one of these
                    127:  * records. 
                    128:  */
                    129: static struct record *instance_method_record   = NULL;
                    130: static struct record *factory_method_record    = NULL;
                    131: 
                    132: /*
                    133:  * This structure is used to translate between selectors and their ASCII
                    134:  * representation.  A NULL terminated array of char*,
                    135:  * OBJC_SELECTOR_REFERENCES, is passed to the constructor routine: 
                    136:  * __objc_execClass. That routine places entries from that array into this
                    137:  * structure.  The location within OBJC_SELECTOR_REFERENCES where the string
                    138:  * was taken from is replaced with a small integer, the index into the array
                    139:  * inside selectorTranslateTable.  That integer then becomes the selector. 
                    140:  *
                    141:  * Selectors begin at 1 to numEntries.  A selector outside of that range is
                    142:  * considered an error.  The selector integers are used as the first index
                    143:  * into the instance_method_record and factory_method_record arrays. 
                    144:  */
                    145: static struct record *selector_record = NULL;
                    146: 
                    147: /*
                    148:  * This data structure is used in the special case where usual fatal error
                    149:  * functions are called but have been overridden in a class.  The value
                    150:  * returned by that function is returned to the calling object.  error_static
                    151:  * holds the returned value until it is retrieved by return_error_static
                    152:  * which returns it to the calling function. 
                    153:  */
                    154: static id      error_static;
                    155: 
                    156: 
                    157: /* Given a class and selector, return the selector's implementation.  */
                    158: static inline IMP      
                    159: get_imp (Class_t class, SEL sel)
                    160: {
                    161:   IMP  imp = NULL;
                    162:   imp = record_get (getClassNumber (class),
                    163:                    record_get ((unsigned int)sel, *class->cache));
                    164: 
                    165:   return imp;
                    166: }
                    167: 
                    168: 
                    169: static void
                    170: error (msg, arg1, arg2)
                    171:      char *msg, *arg1, *arg2;
                    172: {
                    173: #if 0 /* There is no portable way to get the program name.  Too bad.  */
                    174:   fprintf (stderr, "%s: ", programname);
                    175: #endif
                    176:   fprintf (stderr, msg, arg1, arg2);
                    177:   fprintf (stderr, "\n");
                    178: }
                    179: 
                    180: static void
                    181: fatal (msg, arg1, arg2)
                    182:      char *msg, *arg1, *arg2;
                    183: {
                    184:   error (msg, arg1, arg2);
                    185:   exit (1);
                    186: }
                    187: 
                    188: static void *
                    189: xmalloc (unsigned int size)
                    190: {
                    191:   void *ptr = (void *) malloc (size);
                    192:   if (ptr == 0)
                    193:     fatal ("virtual memory exceeded");
                    194:   return ptr;
                    195: }
                    196: 
                    197: static void *
                    198: xcalloc (unsigned int size, unsigned int units)
                    199: {
                    200:   void *ptr = (void *) calloc (size, units);
                    201:   if (ptr == 0)
                    202:     fatal ("virtual memory exceeded");
                    203:   return ptr;
                    204: }
                    205: 
                    206: void *
                    207: __objc_xmalloc (unsigned int size)
                    208: {
                    209:   void *ptr = (void *) malloc (size);
                    210:   if (ptr == 0)
                    211:     fatal ("virtual memory exceeded");
                    212:   return ptr;
                    213: }
                    214: 
                    215: void *
                    216: __objc_xrealloc (void *optr, unsigned int size)
                    217: {
                    218:   void *ptr = (void *) realloc (optr, size);
                    219:   if (ptr == 0)
                    220:     fatal ("virtual memory exceeded");
                    221:   return ptr;
                    222: }
                    223: 
                    224: void *
                    225: __objc_xcalloc (unsigned int size, unsigned int units)
                    226: {
                    227:   void *ptr = (void *) calloc (size, units);
                    228:   if (ptr == 0)
                    229:     fatal ("virtual memory exceeded");
                    230:   return ptr;
                    231: }
                    232: 
                    233: static inline char *
                    234: my_strdup (const char *str)
                    235: {
                    236:   char *new = (char *) xmalloc (strlen (str) + 1);
                    237:   strcpy (new, str);
                    238:        
                    239:   return new;
                    240: }
                    241: 
                    242: 
                    243: /*
                    244:  * This function is called by constructor functions generated for each module
                    245:  * compiled.  
                    246:  *
                    247:  * The purpose of this function is to gather the module pointers so that they
                    248:  * may be processed by the initialization clean up routine. 
                    249:  */
                    250: void 
                    251: __objc_execClass (Module_t module)
                    252: {
                    253:   /* Has we processed any constructors previously? 
                    254:      Flag used to indicate that some global data structures
                    255:      need to be built.  */
                    256:   static BOOL previous_constructors = 0;
                    257: 
                    258:   Symtab_t    symtab = module->symtab;
                    259:   Class_t     object_class;
                    260:   node_ptr node;
                    261:   SEL         *(*selectors)[] = (SEL *(*)[])symtab->refs;
                    262:   int         i;
                    263:   BOOL        incomplete = 0;
                    264: 
                    265: 
                    266:   assert (module->size == sizeof (Module));
                    267:   DEBUG_PRINTF ("received load module: %s\n",module->name);
                    268: 
                    269:   /* Header file data structure hack test.  */
                    270:   assert (sizeof (Class) == sizeof (MetaClass));
                    271: 
                    272:   /* On the first call of this routine, initialize
                    273:      some data structures.  */
                    274:   if (!previous_constructors) {
                    275: 
                    276:     /* Enable malloc debugging. This'll slow'er down! */
                    277: #if defined (DEBUG) && defined (NeXT)
                    278:     malloc_debug (62);
                    279: #endif
                    280: 
                    281:     /* Allocate and initialize the mutex.  */
                    282:     MUTEX_ALLOC (&runtimeMutex);
                    283:     MUTEX_INIT (runtimeMutex);
                    284: 
                    285:     /* Allocate the module hash table.  */
                    286:     module_hash_table
                    287:       = hash_new (MODULE_HASH_SIZE, (hash_func_type)hash_ptr,
                    288:                  (compare_func_type)compare_ptrs);
                    289: 
                    290:     /* Allocate a table for unclaimed categories.  */
                    291:     unclaimed_category_hash_table
                    292:       = hash_new (16, (hash_func_type)hash_ptr,
                    293:                  (compare_func_type)compare_ptrs);
                    294: 
                    295:     /* Allocate a master selector table if it doesn't exist.  */
                    296:     selector_record = record_new ();
                    297:     
                    298:     previous_constructors = 1;
                    299:   }
                    300: 
                    301:   /* Save the module pointer for later processing.  */
                    302:   hash_add (&module_hash_table, module, module);
                    303: 
                    304:   /* Parse the classes in the load module and gather selector information.  */
                    305:   DEBUG_PRINTF ("gathering selectors from module: %s\n",module->name);
                    306:   for (i = 0; i < symtab->cls_def_cnt; ++i) {
                    307:     Class_t class = (Class_t)symtab->defs[i];
                    308: 
                    309:     /* Make sure we have what we think.  */
                    310:     assert (class->info & CLS_CLASS);
                    311:     assert (class->class_pointer->info & CLS_META);
                    312:     DEBUG_PRINTF ("phase 1, processing class: %s\n", class->name);
                    313: 
                    314:     /* Store the class in the class table and assign class numbers.  */
                    315:     addClassToHash (class);
                    316: 
                    317:     /* Store all of the selectors in the class and meta class.  */
                    318:     record_methods_from_class (class);
                    319:     record_methods_from_class ((Class_t)class->class_pointer);
                    320: 
                    321:     /* Initialize the cache pointers.  */
                    322:     class->cache = &instance_method_record;
                    323:     class->class_pointer->cache = &factory_method_record;
                    324:   }
                    325: 
                    326:   /* Replace referenced selectors.  */
                    327:   for (i=0; i < symtab->sel_ref_cnt; ++i)
                    328:     (*selectors)[i] = record_selector ((const char*)(*selectors)[i]);
                    329: 
                    330:   /* Try to build the class hierarchy and initialize the data structures.  */
                    331:   object_class = objc_getClass ("Object");
                    332:   if (object_class) {
                    333:     
                    334:     /* Make sure we have what we think we have.  */
                    335:     assert (object_class->class_pointer->info & CLS_META);
                    336:     assert (object_class->info & CLS_CLASS);
                    337:     
                    338:     /* Connect the classes together (at least as much as we can).  */ 
                    339:     for (node = hash_next (class_hash_table, NULL); node;
                    340:         node = hash_next (class_hash_table, node)) {
                    341:       Class_t class1 = node->value;
                    342: 
                    343:       /* Make sure we have what we think we have.  */
                    344:       assert (class1->info & CLS_CLASS);
                    345:       assert (class1->class_pointer->info & CLS_META);
                    346: 
                    347:       /* The class_pointer of all meta classes point to Object's meta class.  */
                    348:       class1->class_pointer->class_pointer = object_class->class_pointer; 
                    349: 
                    350:       /* Assign super class pointers */
                    351:       if (class1->super_class) {
                    352:        Class_t aSuperClass = objc_getClass ((char*)class1->super_class);
                    353: 
                    354:        if (aSuperClass) {
                    355: 
                    356:          DEBUG_PRINTF ("making class connections for: %s\n", 
                    357:                        class1->name);
                    358: 
                    359:          class1->super_class = aSuperClass; 
                    360:          if (class1->class_pointer->super_class)
                    361:            class1->class_pointer->super_class = class1->super_class->class_pointer;
                    362: 
                    363:          /* Mark the class as initialized.  */
                    364:          class1->info |= CLS_RTI;
                    365:        } else
                    366:          /* Couldn't find the class's super class.  */
                    367:          incomplete = 1;
                    368:       }
                    369:     }
                    370:   } else
                    371:     /* Couldn't find class Object.  */
                    372:     incomplete = 1;
                    373: 
                    374:   /* Process category information from the module.  */
                    375:   for (i = 0; i < symtab->cat_def_cnt; ++i) {
                    376:     Category_t  category = symtab->defs[i + symtab->cls_def_cnt];
                    377:     Class_t     class = objc_getClass (category->class_name);
                    378: 
                    379:     /* If the class for the category exists then append its
                    380:        methods.  */
                    381:     if (class) {
                    382: 
                    383:       DEBUG_PRINTF ("processing categories from (module,object): %s, %s\n",
                    384:                    module->name, 
                    385:                    class_getClassName (class));
                    386: 
                    387:       /* Do instance methods.  */
                    388:       if (category->instance_methods)
                    389:         addMethodsToClass (class, category->instance_methods);
                    390: 
                    391:       /* Do class methods.  */
                    392:       if (category->class_methods)
                    393:         addMethodsToClass ((Class_t)class->class_pointer, category->class_methods);
                    394:     } else {
                    395:       /* The object to which the category methods belong can't
                    396:         be found.  Save the information.  */
                    397:       hash_add (&unclaimed_category_hash_table, category, category);
                    398: 
                    399:       incomplete = 1;
                    400:     }
                    401:   }
                    402: 
                    403:   /* Scan the unclaimed category hash.  
                    404:      Attempt to attach any unclaimed categories to objects.  */
                    405:   for (node = hash_next (unclaimed_category_hash_table, NULL); node;
                    406:        node = hash_next (unclaimed_category_hash_table, node)) {
                    407:     Category_t  category = node->value;
                    408:     Class_t     class = objc_getClass (category->class_name);
                    409: 
                    410:     if (class) {
                    411: 
                    412:       DEBUG_PRINTF ("attaching stored categories to object: %s\n",
                    413:                    class_getClassName (class));
                    414: 
                    415:       /* Delete this class from the hash table.  */
                    416:       hash_remove (unclaimed_category_hash_table, category);
                    417:       node = NULL;
                    418: 
                    419:       if (category->instance_methods)
                    420:        addMethodsToClass (class, category->instance_methods);
                    421: 
                    422:       if (category->class_methods)
                    423:        addMethodsToClass ((Class_t)class->class_pointer,
                    424:                           category->class_methods);
                    425:     } else
                    426:       incomplete = 1;
                    427:   }
                    428: 
                    429:   /* Can we finish the run time initialization? */
                    430:   if (!incomplete) {
                    431: 
                    432:     initialize_dispatch_tables ();
                    433: 
                    434:     /* Debug run time test.
                    435:        We're initialized! */
                    436:     initialized = 1;
                    437: 
                    438:     /* Print out class tables if debugging.  */
                    439:     DEBUG_PRINTF ("dump of class tables from objcInit\n");
                    440:     debug_dump_classes ();
                    441:   }
                    442: 
                    443: }
                    444: 
                    445: 
                    446: IMP  
                    447: objc_msgSend (id receiver, SEL sel)
                    448: {
                    449:   /*
                    450:    * A method is always called by the compiler.  If a method wasn't
                    451:    * found then supply a default. 
                    452:    */
                    453:   IMP  imp = nil_method;
                    454: 
                    455: 
                    456:   /* The run time must be initialized at this point.
                    457:      Otherwise we get a message sent to a object with a bogus selector.  */
                    458:   assert (initialized);
                    459: 
                    460:   /* Objective-C allows messages to be sent to a nil object.  */
                    461:   if (receiver) {
                    462: 
                    463:     /* Check for common programmer error.  */
                    464:     if (!receiver->class_pointer) {
                    465:       fprintf (stderr, "method %s sent to deallocated object %#x\n", 
                    466:               sel_getName (sel), receiver);
                    467:       abort ();
                    468:     }
                    469:     
                    470:     /* Initialize the class if need be.  */
                    471:     if (!(receiver->class_pointer->info & CLS_INITIALIZED))
                    472:       initialize_class (receiver->class_pointer->name);
                    473: 
                    474:     /*
                    475:      * If we're passed a object then its class_pointer is a Class.  If
                    476:      * we're passed a Class then its class_pointer is a MetaClass. 
                    477:      * Therefore, searching for a instance or class method
                    478:      * requires no special decision making here. 
                    479:      *
                    480:      * Look for the method. 
                    481:      */
                    482:     imp = get_imp (receiver->class_pointer, sel);
                    483: 
                    484:     /* If the method cannot be found then perform error handling.  */
                    485:     if (!imp)
                    486:       imp = handle_runtime_error (receiver, sel);
                    487:   }
                    488: 
                    489:   /* Nice debugging messages if enabled.  */
                    490:   if (objc_trace) {
                    491:     printf ("trace: objc_msgSend , obj=%#x, class=%s, method=%s\n",
                    492:            receiver, 
                    493:            receiver->class_pointer->name, 
                    494:            sel_getName (sel));
                    495:     fflush (stdout);
                    496:   }
                    497:   
                    498:   return imp;
                    499: }
                    500: 
                    501: 
                    502: IMP 
                    503: objc_msgSendSuper (Super_t super, SEL sel)
                    504: {
                    505:   IMP  imp;
                    506: 
                    507: 
                    508:   assert (initialized);
                    509: 
                    510:   if (!(super->class->info & CLS_INITIALIZED))
                    511:     initialize_class (super->class->name);
                    512:   if (!(super->receiver->class_pointer->info & CLS_INITIALIZED))
                    513:     initialize_class (super->receiver->class_pointer->name);
                    514: 
                    515:   imp = get_imp (super->class, sel);
                    516:   
                    517:   if (!imp)
                    518:     imp = handle_runtime_error (super->receiver, sel);
                    519: 
                    520:   if (objc_trace) {
                    521:     printf ("trace: objc_msgSendSuper , obj=%#x, class=%s, method=%s\n",
                    522:            super->receiver, 
                    523:            super->receiver->class_pointer->name, 
                    524:            sel_getName (sel));
                    525:     fflush (stdout);
                    526:   }
                    527: 
                    528:   return imp;
                    529: }
                    530: 
                    531: 
                    532: /*
                    533:  * This function is called by objc_msgSend or objc_msgSendSuper when a
                    534:  * message is sent to a object which it does not recognize. 
                    535:  */
                    536: static IMP  
                    537: handle_runtime_error (id object, SEL sel)
                    538: {
                    539:   IMP  imp;
                    540: 
                    541: 
                    542:   /*
                    543:    * If the object recognizes the doesNotRecognize: method then we're
                    544:    * going to send it. 
                    545:    */
                    546:   imp = get_imp (object->class_pointer, sel_getUid ("doesNotRecognize:"));
                    547:   if (imp)
                    548:     error_static = (*imp)(object, sel_getUid ("doesNotRecognize:"), sel);
                    549:   else {
                    550:     /*
                    551:      * The object doesn't recognize the method.  Check for
                    552:      * responding to error:.  If it does then sent it. 
                    553:      */
                    554:     char msg[256 + strlen (sel_getName (sel)) 
                    555:             + strlen (object->class_pointer->name)];
                    556:         
                    557:     sprintf (msg, "%s does not recognize %s", 
                    558:             object->class_pointer->name, sel_getName (sel));
                    559:         
                    560:     imp = get_imp (object->class_pointer, sel_getUid ("error:"));
                    561:     if (imp)
                    562:       error_static = (*imp)(object, sel_getUid ("error:"), msg);
                    563:     else {
                    564:       /*
                    565:        * The object doesn't respond to doesNotRecognize: or
                    566:        * error:;  Therefore, a default action is taken. 
                    567:        */
                    568:       fprintf (stderr, "%s\n", msg);
                    569:       abort ();
                    570:     }
                    571:   }
                    572: 
                    573:   /*
                    574:    * Either doesNotRecognize: or error: has been overridden.  We have
                    575:    * to return that value as the default action. 
                    576:    */
                    577:   return return_error_static;
                    578: }
                    579: 
                    580: 
                    581: /*
                    582:  * This function is used by the run-time to provide a method where nil
                    583:  * objects can receive messages. 
                    584:  *
                    585:  * This method simply returns self. 
                    586:  */
                    587: static id  
                    588: nil_method (id object, SEL sel, ...)
                    589: {
                    590:   return object;
                    591: }
                    592: 
                    593: 
                    594: /*
                    595:  * This function is used by the run-time to provide a method where nil
                    596:  * objects can receive messages. 
                    597:  *
                    598:  * This method simply returns self. 
                    599:  *
                    600:  * Note: multiple thread problem area. 
                    601:  */
                    602: static id  
                    603: return_error_static (id object, SEL sel, ...)
                    604: {
                    605:   return error_static;
                    606: }
                    607: 
                    608: 
                    609: /*
                    610:  * These variables provide a way for the defalut methods of object
                    611:  * allocation, destruction, and reallocation to be overridden. 
                    612:  */
                    613: id    (*_alloc)(Class_t)                  = objc_object_create;
                    614: id    (*_dealloc)(id)                     = objc_object_dispose;
                    615: id    (*_realloc)(id, unsigned int)              = objc_object_realloc;
                    616: id    (*_copy)(id)                        = objc_object_copy;
                    617: void  (*_error)(id, const char*, va_list) = objc_error;
                    618: 
                    619: 
                    620: id 
                    621: objc_object_create (Class_t class)
                    622: {
                    623:   id     object;
                    624: 
                    625: 
                    626:   assert (class);
                    627: 
                    628:   /*
                    629:    * Allocate memory for the object, initialize the memory to 0, and
                    630:    * set the object's class_pointer. 
                    631:    *
                    632:    * The object's class_pointer is the class's TEXT image.  It is used by
                    633:    * the messager as the key to the class hash for methods. 
                    634:    *
                    635:    * No need to initialize the class.  That was done in objcInit. 
                    636:    */
                    637:   object = (id) xcalloc (1, class->instance_size);
                    638:   object->class_pointer = class;
                    639: 
                    640:   return object;
                    641: }
                    642: 
                    643: 
                    644: id  
                    645: objc_object_dispose (id object)
                    646: {
                    647:   object->class_pointer = NULL;
                    648:   free (object);
                    649: 
                    650:   return nil;
                    651: }
                    652: 
                    653: 
                    654: id  
                    655: objc_object_realloc (id object, unsigned int length)
                    656: {
                    657:   id  obj;
                    658:   /* Can't resize a object smaller than its instance size.  */
                    659:   /* Don't use assert here;
                    660:      checks for user errors shouldn't depend on NDEBUG.  */
                    661:   if (length < object->class_pointer->instance_size)
                    662:     abort ();
                    663: 
                    664:   obj = (id) realloc (object, length);
                    665:   bzero ((char*)obj + object->class_pointer->instance_size,  
                    666:         length - object->class_pointer->instance_size);
                    667:   
                    668:   return obj;
                    669: }
                    670: 
                    671: 
                    672: id  
                    673: objc_object_copy (id object)
                    674: {
                    675:   id  obj;
                    676:   obj = class_createInstance (object->class_pointer);
                    677:   bcopy (object, obj, objc_classSize (object));
                    678:   
                    679:   return obj;
                    680: }
                    681: 
                    682: 
                    683: void  
                    684: objc_error (id object, const char *fmt, va_list ap)
                    685: {
                    686:   vfprintf (stderr, fmt, ap);
                    687:   abort ();
                    688: }
                    689: 
                    690: 
                    691: /* Silly function to skip past a sequence of digits in a string.  */
                    692: static inline const char *
                    693: skip_digits (const char *str)
                    694: {
                    695:   while (isdigit (*str))
                    696:     ++str;
                    697: 
                    698:   return str;
                    699: }
                    700: 
                    701: 
                    702: unsigned int 
                    703: method_getNumberOfArguments (Method_t method)
                    704: {
                    705:   unsigned int       num = 0;
                    706:   const char *args = &method->method_types[1];
                    707:   
                    708:   
                    709:   while (*args) {
                    710:   
                    711:     /* Skip past size info.  */
                    712:     args = skip_digits (args);
                    713:     
                    714:     /* Argument type next.  */
                    715:     assert (*args);
                    716:     ++num;
                    717:     
                    718:     /* Step to next arg.  */
                    719:     ++args;
                    720:   }
                    721:   
                    722:   assert (num >= 2);
                    723:   return num;
                    724: }
                    725: 
                    726: 
                    727: unsigned int 
                    728: method_getArgumentInfo (Method_t method, int indx, const char **type, 
                    729:                        int *offset)
                    730: {
                    731:   const char *args = skip_digits (&method->method_types[1]);
                    732:   int         i;
                    733: 
                    734:   
                    735:   assert (method_getNumberOfArguments (method) >= indx);
                    736: 
                    737:   /* Step to arg.  */
                    738:   for (i = 0; i < indx; ++i) {
                    739:     ++args;
                    740:     args = skip_digits (args);
                    741:   }
                    742:   
                    743:   /* Return arg data.  */
                    744:   *type = args++;
                    745:   *offset = atoi (args);
                    746:   
                    747:   return indx;
                    748: }
                    749: 
                    750: 
                    751: /* This function is not thread safe.  */
                    752: Ivar_t  
                    753: object_getIvarAddress (id object, const char *name)
                    754: {
                    755:   Class_t class = object->class_pointer; /* Here is the thread safe problem.  */
                    756:   Ivar_t  ivar = NULL;
                    757:   
                    758: 
                    759:   do {
                    760:     IvarList_t  ivars = class->ivars;
                    761:     int         i;
                    762:       
                    763:     /* Look at all of the ivar names.  */
                    764:     for (i = 0; i < ivars->ivar_count; ++i)
                    765:       if (!strcmp (name, ivars->ivar_list[i].ivar_name))
                    766:         ivar = &ivars->ivar_list[i];
                    767:            
                    768:     /*
                    769:      * If the ivar wasn't found then lets look to the
                    770:      * super class. 
                    771:      *
                    772:      * If the class is Object then the super class is NULL
                    773:      * and we're done. 
                    774:      */
                    775:     class = class->super_class;
                    776:         
                    777:   } while (!ivar && class);
                    778: 
                    779:   return ivar;
                    780: }
                    781: 
                    782: 
                    783: /*
                    784:  * Search for a method starting from the current class up its hierarchy.  
                    785:  *
                    786:  * Return a pointer to the method's method structure if found.  NULL otherwise. 
                    787:  */
                    788: Method_t  
                    789: searchForMethodInHierarchy (Class_t class, SEL sel)
                    790: {
                    791:   Method_t     method = NULL;
                    792:   const char*  name;
                    793: 
                    794:   if (sel == 0)
                    795:     return NULL;
                    796: 
                    797:   name = sel_getName (sel);
                    798: 
                    799:   if (name == 0)
                    800:     return NULL;
                    801: 
                    802:   /*
                    803:    * Scan the method list of the class.  If the method isn't found in
                    804:    * the list then step to its super class. 
                    805:    */
                    806:   do {
                    807:     
                    808:     method = searchForMethodInList (class->methods, name);
                    809:     class = class->super_class;
                    810: 
                    811:   } while (!method && class);
                    812:     
                    813:   return method;
                    814: }
                    815: 
                    816: 
                    817: /*
                    818:  * Given a linked list of method and a method's name.  Search for the named
                    819:  * method's method structure. 
                    820:  *
                    821:  * Return a pointer to the method's method structure if found.  NULL otherwise. 
                    822:  */
                    823: Method_t  
                    824: searchForMethodInList (MethodList_t list, const char *name)
                    825: {
                    826:   MethodList_t  method_list = list;
                    827:   
                    828: 
                    829:   /* Check for bumbling.  */
                    830:   /* ??? Who generates the name?  Is it the user, or part of this file?
                    831:      If we crash here, whose fault is it?  */
                    832:   assert (name);
                    833: 
                    834:   /* If not found then we'll search the list.  */
                    835:   while (method_list) {
                    836:     int   i;
                    837:   
                    838:     /* Search the method list.  */
                    839:     for (i = 0; i < method_list->method_count; ++i) {
                    840:       Method_t method = &method_list->method_list[i];
                    841: 
                    842:       if (method->method_name)
                    843:        if (!strcmp (method->method_name, name))
                    844:          return method;
                    845:     }
                    846:         
                    847:     /* The method wasn't found.  Follow the link to the next list of 
                    848:        methods.  */
                    849:     method_list = method_list->method_next;
                    850:   }
                    851:   
                    852:   return NULL;
                    853: }
                    854: 
                    855: 
                    856: /*
                    857:  * This function adds a method list to a class.  
                    858:  *
                    859:  * This function is typically called by another function specific to the
                    860:  * run-time.  As such this function does not worry about thread safe issued.  
                    861:  */
                    862: void  
                    863: addMethodsToClass (Class_t class, MethodList_t list)
                    864: {
                    865:   int i;
                    866:   
                    867:   
                    868:   /* Passing of a linked list is not allowed.  Do multiple calls.  */
                    869:   assert (!list->method_next);
                    870: 
                    871:   /* Check for duplicates.  */ 
                    872:   for (i = 0; i < list->method_count; ++i) {
                    873:     Method_t  method = &list->method_list[i];
                    874: 
                    875:     if (method->method_name)   /* Sometimes these are NULL */
                    876:       if (searchForMethodInList (class->methods, method->method_name)) {
                    877:        /*
                    878:         * Duplication. Print a error message an change the
                    879:         * method name to NULL. 
                    880:         */
                    881:        fprintf (stderr, "attempt to add a existing method: %s\n",
                    882:                 method->method_name);
                    883:        method->method_name = NULL;
                    884:       }
                    885:   }
                    886:   
                    887:   /* Add the methods to the class's method list.  */
                    888:   list->method_next = class->methods;
                    889:   class->methods = list;
                    890: }
                    891: 
                    892: 
                    893: /*
                    894:  * This function removes the instance and factory methods in the passed list
                    895:  * from a class.  
                    896:  *
                    897:  * Methods are removed from a class by replacing the method's name with NULL. 
                    898:  *
                    899:  *
                    900:  * This function is typically called by another function specific to the
                    901:  * run-time.  As such this function does not worry about thread safe issued.  
                    902:  */
                    903: void  
                    904: class_removeMethods (Class_t class, MethodList_t method_list)
                    905: {
                    906:   int i;
                    907:   
                    908:   
                    909:   /* Passing of a linked list is not allowed.  Do multiple calls.  */
                    910:   assert (!method_list->method_next);
                    911: 
                    912:   /*
                    913:    * For each method in the list search the method lists erasing any
                    914:    * entries found. 
                    915:    */
                    916:   for (i = 0; i < method_list->method_count; ++i) {
                    917:     Method_t  kill_method = &method_list->method_list[i];
                    918:     Method_t  method;
                    919: 
                    920:     /* Remove any instance method found.  */
                    921:     method = searchForMethodInList (class->methods, 
                    922:                                    kill_method->method_name);
                    923:     if (method)
                    924:       method->method_name = NULL;
                    925:       
                    926:     /* Remove any factory method found.  */
                    927:     method = searchForMethodInList (class->class_pointer->methods, 
                    928:                                    kill_method->method_name);
                    929:     if (method)
                    930:       method->method_name = NULL;
                    931:   }
                    932: }
                    933: 
                    934: 
                    935: /*
                    936:  * This is a incomplete implementation of posing.   This function does the
                    937:  * bulk of the work but does not initialize the class method caches.  That is
                    938:  * a run-time specific operation. 
                    939:  *
                    940:  * I implement posing by hiding SUPER_CLASS, creating new class and meta
                    941:  * class structures, initializing it with IMPOSTOR, and changing it such
                    942:  * that it is identified as SUPER_CLASS. SUPER_CLASS remains in the
                    943:  * hierarchy but is inaccessible by the means. The class hierarchy is then re
                    944:  * arranged such that all of the subclasses of SUPER_CLASS now inherit from
                    945:  * the new class structures -- except the impostor itself. The only dramatic
                    946:  * effect on the application is that subclasses of SUPER_CLASS cannot do a 
                    947:  * [ ....  superClass ] and expect their real super class. 
                    948:  */
                    949: Class_t 
                    950: class_poseAs (Class_t impostor, Class_t super_class)
                    951: {
                    952:   Class_t     new_class = (Class_t) calloc (1, sizeof (Class));
                    953:   MetaClass_t new_meta_class = (MetaClass_t) calloc (1, sizeof (MetaClass));
                    954:   node_ptr node;
                    955:   char        *new_name = (char *) malloc (strlen (super_class->name) + 12);
                    956: 
                    957:   
                    958:   assert (new_class);
                    959:   assert (new_meta_class);
                    960:   assert (new_name);
                    961: 
                    962:   /* No dispatching while the the posing class is being built.
                    963:      The dispatch tables will be hacked on.  */
                    964:   MUTEX_LOCK (runtimeMutex);
                    965:        
                    966:   assert (impostor->info & CLS_CLASS);
                    967:   assert (super_class->info & CLS_CLASS);
                    968: 
                    969:   assert (impostor->instance_size == super_class->instance_size);
                    970: 
                    971:   /* Create the impostor class.  */
                    972:   new_class->class_pointer     = new_meta_class;
                    973:   new_class->super_class       = super_class;
                    974:   new_class->name              = super_class->name;
                    975:   new_class->version           = super_class->version;
                    976:   new_class->info              = super_class->info;
                    977:   new_class->instance_size     = super_class->instance_size;
                    978:   new_class->ivars             = super_class->ivars;
                    979:   new_class->methods           = impostor->methods;
                    980:   new_class->cache           = &instance_method_record;
                    981:   
                    982:   /* Create the impostor meta class.  */
                    983:   new_meta_class->class_pointer = super_class->class_pointer->class_pointer;
                    984:   new_meta_class->super_class   = super_class->class_pointer->super_class;
                    985:   new_meta_class->name          = super_class->class_pointer->name;
                    986:   new_meta_class->version       = super_class->class_pointer->version;
                    987:   new_meta_class->info          = super_class->class_pointer->info;
                    988:   new_meta_class->instance_size = super_class->class_pointer->instance_size;
                    989:   new_meta_class->ivars         = super_class->class_pointer->ivars;
                    990:   new_meta_class->methods       = impostor->class_pointer->methods;
                    991:   new_meta_class->cache              = &factory_method_record;
                    992: 
                    993:   /*
                    994:    * Delete the class from the hash table, change its name so that it
                    995:    * can no longer be found, then place it back into the hash table
                    996:    * using its new name. 
                    997:    *
                    998:    * Don't worry about the class number.  It is already assigned. 
                    999:    *
                   1000:    * Don't worry about dangling pointers.  Life's a bitch.  (A little bit
                   1001:    * of memory is lost with the hash key.)
                   1002:    */
                   1003:   hash_remove (class_hash_table, super_class->name);
                   1004:   sprintf (new_name, "%s*", super_class->name);
                   1005:   super_class->name       = new_name;
                   1006:   super_class->class_pointer->name  = new_name;
                   1007:   hash_add (&class_hash_table, super_class->name, super_class);
                   1008:   
                   1009:   /*
                   1010:    * Now change all of the classes derived from super_class to be
                   1011:    * derived from a impostor (except the impostor's impostor. 
                   1012:    */
                   1013:   for (node = hash_next (class_hash_table, NULL); node;
                   1014:        node = hash_next (class_hash_table, node)) {
                   1015:                
                   1016:     Class_t    class1 = node->value;
                   1017:     
                   1018:     if (class1->super_class == super_class)
                   1019:       if (class1 != impostor)
                   1020:         class1->super_class = new_class;
                   1021:   }
                   1022: 
                   1023:   /* Place the impostor class in class hash table
                   1024:      and assign it a class number.  */
                   1025:   addClassToHash (new_class);
                   1026: 
                   1027:   /* Reinitialize the dispatch tables.  */
                   1028:   initialize_dispatch_tables ();
                   1029: 
                   1030:   MUTEX_UNLOCK (runtimeMutex);
                   1031: 
                   1032:   /* Print out class tables if debugging.  */
                   1033:   DEBUG_PRINTF ("dump of class tables class_poseAs\n");
                   1034:   debug_dump_classes ();
                   1035: 
                   1036:   return new_class;
                   1037: }
                   1038: 
                   1039: 
                   1040: /*
                   1041:  * This routine is given a class and records all of the methods in its class
                   1042:  * structure in the record table.  
                   1043:  */
                   1044: static void
                   1045: record_methods_from_class (Class_t class)
                   1046: {
                   1047:   MethodList_t method_list;
                   1048:        
                   1049:        
                   1050:   method_list = class->methods;
                   1051:   while (method_list) {
                   1052:     record_methods_from_list (method_list);
                   1053:     method_list = method_list->method_next;
                   1054:   }
                   1055: }
                   1056: 
                   1057: 
                   1058: /*
                   1059:  * This routine is given a list of methods and records each of the methods in
                   1060:  * the record table.  This is the routine that does the actual recording
                   1061:  * work. 
                   1062:  */
                   1063: static void
                   1064: record_methods_from_list (MethodList_t method_list)
                   1065: {
                   1066:   int  i;
                   1067:        
                   1068:        
                   1069:   for (i = 0; i < method_list->method_count; ++i) {
                   1070:     Method_t method = &method_list->method_list[i];
                   1071: 
                   1072:     record_selector (method->method_name);
                   1073:   }
                   1074: }
                   1075: 
                   1076: 
                   1077: SEL
                   1078: sel_getUid (const STR name)
                   1079: {
                   1080:   int i;
                   1081:        
                   1082:        
                   1083:   for (i = 1; i <= record_entries (selector_record); ++i)
                   1084:     if (!strcmp (name, record_get (i, selector_record)))
                   1085:       return (SEL)i;
                   1086:        
                   1087:   /* Unable to locate selector.  Return error value.  */
                   1088:   return (SEL)0;
                   1089: }
                   1090: 
                   1091: 
                   1092: STR
                   1093: sel_getName (SEL selector)
                   1094: {
                   1095:   return record_get ((unsigned int)selector, selector_record);
                   1096: }
                   1097: 
                   1098: 
                   1099: /*
                   1100:  * Store the passed selector name in the selector record and return its
                   1101:  * selector value (value returned by sel_getUid). 
                   1102:  */
                   1103: static SEL
                   1104: record_selector (const char *sel)
                   1105: {
                   1106:   int j;
                   1107:        
                   1108:                        
                   1109:   /* Find either the selector in the table or an empty slot.  */
                   1110:   for (j = 1; j <= record_entries (selector_record); ++j)
                   1111:     if (!strcmp (sel,  record_get (j, selector_record)))
                   1112:       return (SEL)j;
                   1113:                        
                   1114:   /* Save the selector name.  */
                   1115:   record_store (my_strdup (sel), selector_record);
                   1116:   DEBUG_PRINTF ("Record: %s as: %#x\n", sel, j);
                   1117: 
                   1118:   return (SEL)j;               
                   1119: }
                   1120: 
                   1121: 
                   1122: /*
                   1123:  * Initialize the dispatch tables.  This requires the initialization of the
                   1124:  * instance_method_record and factory_method_record arrays and the arrays they
                   1125:  * point to. 
                   1126:  *
                   1127:  * The first array is indexed by a class number.  Therefore its size is the
                   1128:  * number of classes in the executable.  The second array is indexed by a
                   1129:  * selector id.  Therefore its size is the number of unique selectors in the
                   1130:  * application. 
                   1131:  *
                   1132:  * When a method is sent to a object its class number is extracted from the
                   1133:  * class structure and used in the first array.  The selector id is used in
                   1134:  * the second.  The result value is a method implementation. 
                   1135:  */
                   1136: static void
                   1137: initialize_dispatch_tables (void)
                   1138: {
                   1139:   int  i;
                   1140: 
                   1141: 
                   1142:   /* Check to make sure things are in place.  */
                   1143:   assert (selector_record);
                   1144: 
                   1145:   /* Blow away the instance and factory method records.  */
                   1146:   if (factory_method_record) {
                   1147:     for (i = 1; i <= record_entries (factory_method_record); ++i)
                   1148:       record_delete (record_get (i, factory_method_record));
                   1149:     record_delete (factory_method_record);
                   1150:   }
                   1151:   if (instance_method_record) {
                   1152:     for (i = 1; i <= record_entries (instance_method_record); ++i)
                   1153:       record_delete (record_get (i, instance_method_record));
                   1154:     record_delete (instance_method_record);
                   1155:   }
                   1156: 
                   1157:   /* Reallocate the instance and factory method records.  */
                   1158:   factory_method_record = record_new ();
                   1159:   instance_method_record = record_new ();
                   1160:   for (i = 1; i <= record_entries (selector_record); ++i) {
                   1161:     record_store (record_new (), factory_method_record);
                   1162:     record_store (record_new (), instance_method_record);
                   1163:   }
                   1164:        
                   1165:   /* Fool all of the secondary records into thinking they have data.  */
                   1166:   for (i = 1; i <= record_entries (selector_record); ++i) {
                   1167:     struct record *record;
                   1168:     node_ptr   node;
                   1169:        
                   1170:     record = record_get (i, factory_method_record);
                   1171:     for (node = hash_next (module_hash_table, NULL); node;
                   1172:         node = hash_next (module_hash_table, node))
                   1173:       record_store (NULL, record);
                   1174:                        
                   1175:     record = record_get (i, instance_method_record);
                   1176:     for (node = hash_next (module_hash_table, NULL); node;
                   1177:         node = hash_next (module_hash_table, node))
                   1178:       record_store (NULL, record);
                   1179:   }    
                   1180:        
                   1181:   /* For all classes fill in the methods implemented by the class and visiable
                   1182:      from the class in the hierarchy.  Those methods are assigned to the
                   1183:      class.  */
                   1184:   for (i = 1; i <= record_entries (selector_record); ++i) { /* i is a sel */
                   1185:     node_ptr   node;
                   1186:        
                   1187:     for (node = hash_next (class_hash_table, NULL); node;
                   1188:         node = hash_next (class_hash_table, node)) {
                   1189:       Class_t     class = node->value;
                   1190:       MetaClass_t meta_class = class->class_pointer;
                   1191:       int        class_number = getClassNumber (class);
                   1192:       Method_t    method;
                   1193: 
                   1194:       /* DEBUG_PRINTF ("Assignment of sel=%s, class=%s (%#x, %#x)\n", 
                   1195:         sel_getName ((SEL)i), class->name,
                   1196:         searchForMethodInHierarchy (class, (SEL)i),
                   1197:         searchForMethodInHierarchy ((Class_t)meta_class, (SEL)i)); */
                   1198: 
                   1199:       method = searchForMethodInHierarchy (class, (SEL)i);
                   1200:       if (method)
                   1201:        record_store_at (class_number, method->method_imp,
                   1202:                         record_get (i, instance_method_record));
                   1203: 
                   1204:       assert (class_number == getClassNumber ((Class_t)class->class_pointer));
                   1205:       method = searchForMethodInHierarchy ((Class_t)meta_class, (SEL)i);
                   1206:       if (method)
                   1207:         record_store_at (class_number, method->method_imp,
                   1208:                          record_get (i, factory_method_record));
                   1209:     }
                   1210:   }
                   1211: }
                   1212: 
                   1213: 
                   1214: /*
                   1215:  * This method is called by the dispatch routines when a class has not been
                   1216:  * initialized.  This method is responsible for initializing the class.  This
                   1217:  * is accomplished by first testing the class itself for responding to the
                   1218:  * +initialize method.  If such a method is implemented then it is called. 
                   1219:  * Before exit, irregardless if the class implements +initialize, the class
                   1220:  * is marked as initialized. 
                   1221:  */
                   1222: static void            
                   1223: initialize_class (const char *name)
                   1224: {
                   1225:   Method_t     method = NULL;
                   1226:   Class_t      class = objc_getClass (name);
                   1227:   SEL          sel = sel_getUid ("initialize");
                   1228: 
                   1229:        
                   1230:   /* The class should not be initialized at this point.  */
                   1231:   assert (!(class->info & CLS_INITIALIZED));
                   1232:   assert (!(class->class_pointer->info & CLS_INITIALIZED));
                   1233: 
                   1234:   /* Search for the +initialize method.
                   1235:      Call it if it exists.  */
                   1236:   if (sel)
                   1237:     method = searchForMethodInList (class->class_pointer->methods,
                   1238:                                    sel_getName (sel));
                   1239:   if (method) {
                   1240:     IMP        imp;
                   1241: 
                   1242:     DEBUG_PRINTF ("Class: %s sending +%s\n", 
                   1243:                  name, sel_getName (sel));
                   1244:     imp = get_imp ((Class_t)class->class_pointer, sel);
                   1245:     assert (imp);
                   1246:     (*imp)((id)class, sel);
                   1247:   }
                   1248: 
                   1249:   /* Mark the class as initialized.  */
                   1250:   class->info  |= CLS_INITIALIZED;
                   1251:   class->class_pointer->info   |= CLS_INITIALIZED;
                   1252: }
                   1253: 
                   1254: 
                   1255: /*
                   1256:  * Silly little function that checks to make sure the class hash table is
                   1257:  * initialized.  If it isn't initialized then do it. 
                   1258:  */
                   1259: static inline void
                   1260: class_hash_init (void)
                   1261: {
                   1262:   static unsigned int  init = 0;
                   1263:        
                   1264:        
                   1265:   if (!init)
                   1266:     class_hash_table = hash_new (CLASS_HASH_SIZE, 
                   1267:                                 (hash_func_type)hash_string,
                   1268:                                 (compare_func_type)compare_strings);
                   1269:   init = 1;
                   1270: }
                   1271: 
                   1272: 
                   1273: Class_t 
                   1274: objc_getClass (const char *name)
                   1275: {
                   1276:   Class_t      class;
                   1277: 
                   1278: 
                   1279:   /* Make sure the class hash table exists.  */
                   1280:   class_hash_init ();
                   1281: 
                   1282:   class = hash_value_for_key (class_hash_table, name);
                   1283:        
                   1284:   return class;
                   1285: }
                   1286: 
                   1287: 
                   1288: MetaClass_t 
                   1289: objc_getMetaClass (const char *name)
                   1290: {
                   1291:   /* Meta classes are pointed to by the class's class_pointer.
                   1292:      Just get the class and return its class_pointer.  */
                   1293:   return (objc_getClass (name))->class_pointer;
                   1294: }
                   1295: 
                   1296: 
                   1297: void
                   1298: addClassToHash (Class_t class)
                   1299: {
                   1300:   Class_t      hClass;
                   1301:        
                   1302:        
                   1303:   class_hash_init ();
                   1304: 
                   1305:   /* Check to see if the class is already in the hash table.  */
                   1306:   hClass = hash_value_for_key (class_hash_table, class->name);
                   1307:   if (!hClass) {
                   1308:     
                   1309:     /* The class isn't in the hash table.  Add the class and 
                   1310:        assign a class number.  */
                   1311:     static unsigned int        class_number = 1;
                   1312:        
                   1313:     setClassNumber (class, class_number);
                   1314:     setClassNumber ((Class_t)class->class_pointer, class_number);
                   1315:     ++class_number;
                   1316:     
                   1317:     hash_add (&class_hash_table, class->name, class);
                   1318:   }
                   1319: }
                   1320: 
                   1321: 
                   1322: void  
                   1323: debug_dump_classes (void)
                   1324: {
                   1325:   node_ptr node;
                   1326:   int         i;
                   1327: 
                   1328: 
                   1329:   DEBUG_PRINTF ("class tables\n");
                   1330:   i = 0;
                   1331:   for (node = hash_next (class_hash_table, NULL); node; 
                   1332:        node = hash_next (class_hash_table, node)) {
                   1333: 
                   1334:     Class_t class = node->value;
                   1335:       
                   1336:     DEBUG_PRINTF ("Class { /*%#x*/\n", class);
                   1337:     DEBUG_PRINTF ("   MetaClass_t  class_pointer = %#x\n", class->class_pointer);
                   1338:     DEBUG_PRINTF ("   Class_t      super_class   = %#x\n", class->super_class);
                   1339:     DEBUG_PRINTF ("   char         *name          = %s\n", class->name);
                   1340:     DEBUG_PRINTF ("   long         version       = %ld\n", class->version);
                   1341:     DEBUG_PRINTF ("   long         info          = %#x\n", class->info);
                   1342:     DEBUG_PRINTF ("   long         instance_size = %ld\n", class->instance_size);
                   1343:     DEBUG_PRINTF ("   IvarList_t   ivars         = %#x\n", class->ivars);
                   1344:     DEBUG_PRINTF ("   MethodList_t methods       = %#x\n", class->methods);
                   1345:     DEBUG_PRINTF ("   cache_ptr      cache         = %#x\n", class->cache);
                   1346:     DEBUG_PRINTF ("}[%d];\n", i++);
                   1347:   }
                   1348:     
                   1349:   i = 0;
                   1350:   for (node = hash_next (class_hash_table, NULL); node; 
                   1351:     node = hash_next (class_hash_table, node)) {
                   1352: 
                   1353:     Class_t class = (Class_t)((Class_t)(node->value))->class_pointer;
                   1354:       
                   1355:     DEBUG_PRINTF ("MetaClass { /*%#x*/\n", class);
                   1356:     DEBUG_PRINTF ("   MetaClass_t  class_pointer = %#x\n", class->class_pointer);
                   1357:     DEBUG_PRINTF ("   MetaClass_t  super_class   = %#x\n", class->super_class);
                   1358:     DEBUG_PRINTF ("   char         *name          = %s\n", class->name);
                   1359:     DEBUG_PRINTF ("   long         version       = %ld\n", class->version);
                   1360:     DEBUG_PRINTF ("   long         info          = %#x\n", class->info);
                   1361:     DEBUG_PRINTF ("   long         instance_size = %ld\n", class->instance_size);
                   1362:     DEBUG_PRINTF ("   IvarList_t   ivars         = %#x\n", class->ivars);
                   1363:     DEBUG_PRINTF ("   MethodList_t methods       = %#x\n", class->methods);
                   1364:     DEBUG_PRINTF ("   cache_ptr      cache         = %#x\n", class->cache);
                   1365:     DEBUG_PRINTF ("}[%d];\n", i++);
                   1366:   }
                   1367: }
                   1368: 

unix.superglobalmegacorp.com

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