home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gcc-2.3.3-src.lha / gcc-2.3.3 / objc / core.c next >
Encoding:
C/C++ Source or Header  |  1994-02-07  |  38.4 KB  |  1,369 lines

  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.  
  1369.