home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / Programming / c-runtime / dispatch / RCS / core.c,v next >
Encoding:
Text File  |  1992-08-18  |  37.7 KB  |  1,380 lines

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