⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
   */  for (i = 0; i < method_list->method_count; ++i) {    Method_t  kill_method = &method_list->method_list[i];    Method_t  method;    /* Remove any instance method found.  */    method = searchForMethodInList (class->methods, 				    kill_method->method_name);    if (method)      method->method_name = NULL;          /* Remove any factory method found.  */    method = searchForMethodInList (class->class_pointer->methods, 				    kill_method->method_name);    if (method)      method->method_name = NULL;  }}/* * This is a incomplete implementation of posing.   This function does the * bulk of the work but does not initialize the class method caches.  That is * a run-time specific operation.  * * I implement posing by hiding SUPER_CLASS, creating new class and meta * class structures, initializing it with IMPOSTOR, and changing it such * that it is identified as SUPER_CLASS. SUPER_CLASS remains in the * hierarchy but is inaccessible by the means. The class hierarchy is then re * arranged such that all of the subclasses of SUPER_CLASS now inherit from * the new class structures -- except the impostor itself. The only dramatic * effect on the application is that subclasses of SUPER_CLASS cannot do a  * [ ....  superClass ] and expect their real super class.  */Class_t class_poseAs (Class_t impostor, Class_t super_class){  Class_t     new_class = (Class_t) calloc (1, sizeof (Class));  MetaClass_t new_meta_class = (MetaClass_t) calloc (1, sizeof (MetaClass));  node_ptr node;  char        *new_name = (char *) malloc (strlen (super_class->name) + 12);    assert (new_class);  assert (new_meta_class);  assert (new_name);  /* No dispatching while the the posing class is being built.     The dispatch tables will be hacked on.  */  MUTEX_LOCK (runtimeMutex);	  assert (impostor->info & CLS_CLASS);  assert (super_class->info & CLS_CLASS);  assert (impostor->instance_size == super_class->instance_size);  /* Create the impostor class.  */  new_class->class_pointer     = new_meta_class;  new_class->super_class       = super_class;  new_class->name              = super_class->name;  new_class->version           = super_class->version;  new_class->info              = super_class->info;  new_class->instance_size     = super_class->instance_size;  new_class->ivars             = super_class->ivars;  new_class->methods           = impostor->methods;  new_class->cache	      = &instance_method_record;    /* Create the impostor meta class.  */  new_meta_class->class_pointer = super_class->class_pointer->class_pointer;  new_meta_class->super_class   = super_class->class_pointer->super_class;  new_meta_class->name          = super_class->class_pointer->name;  new_meta_class->version       = super_class->class_pointer->version;  new_meta_class->info          = super_class->class_pointer->info;  new_meta_class->instance_size = super_class->class_pointer->instance_size;  new_meta_class->ivars         = super_class->class_pointer->ivars;  new_meta_class->methods       = impostor->class_pointer->methods;  new_meta_class->cache	      = &factory_method_record;  /*   * Delete the class from the hash table, change its name so that it   * can no longer be found, then place it back into the hash table   * using its new name.    *   * Don't worry about the class number.  It is already assigned.    *   * Don't worry about dangling pointers.  Life's a bitch.  (A little bit   * of memory is lost with the hash key.)   */  hash_remove (class_hash_table, super_class->name);  sprintf (new_name, "%s*", super_class->name);  super_class->name       = new_name;  super_class->class_pointer->name  = new_name;  hash_add (&class_hash_table, super_class->name, super_class);    /*   * Now change all of the classes derived from super_class to be   * derived from a impostor (except the impostor's impostor.    */  for (node = hash_next (class_hash_table, NULL); node;       node = hash_next (class_hash_table, node)) {		    Class_t	class1 = node->value;        if (class1->super_class == super_class)      if (class1 != impostor)        class1->super_class = new_class;  }  /* Place the impostor class in class hash table     and assign it a class number.  */  addClassToHash (new_class);  /* Reinitialize the dispatch tables.  */  initialize_dispatch_tables ();  MUTEX_UNLOCK (runtimeMutex);  /* Print out class tables if debugging.  */  DEBUG_PRINTF ("dump of class tables class_poseAs\n");  debug_dump_classes ();  return new_class;}/* * This routine is given a class and records all of the methods in its class * structure in the record table.   */static voidrecord_methods_from_class (Class_t class){  MethodList_t	method_list;		  method_list = class->methods;  while (method_list) {    record_methods_from_list (method_list);    method_list = method_list->method_next;  }}/* * This routine is given a list of methods and records each of the methods in * the record table.  This is the routine that does the actual recording * work.  */static voidrecord_methods_from_list (MethodList_t method_list){  int	i;		  for (i = 0; i < method_list->method_count; ++i) {    Method_t method = &method_list->method_list[i];    record_selector (method->method_name);  }}SELsel_getUid (const STR name){  int i;		  for (i = 1; i <= record_entries (selector_record); ++i)    if (!strcmp (name, record_get (i, selector_record)))      return (SEL)i;	  /* Unable to locate selector.  Return error value.  */  return (SEL)0;}STRsel_getName (SEL selector){  return record_get ((unsigned int)selector, selector_record);}/* * Store the passed selector name in the selector record and return its * selector value (value returned by sel_getUid).  */static SELrecord_selector (const char *sel){  int j;				  /* Find either the selector in the table or an empty slot.  */  for (j = 1; j <= record_entries (selector_record); ++j)    if (!strcmp (sel,  record_get (j, selector_record)))      return (SEL)j;			  /* Save the selector name.  */  record_store (my_strdup (sel), selector_record);  DEBUG_PRINTF ("Record: %s as: %#x\n", sel, j);  return (SEL)j;		}/* * Initialize the dispatch tables.  This requires the initialization of the * instance_method_record and factory_method_record arrays and the arrays they * point to.  * * The first array is indexed by a class number.  Therefore its size is the * number of classes in the executable.  The second array is indexed by a * selector id.  Therefore its size is the number of unique selectors in the * application.  * * When a method is sent to a object its class number is extracted from the * class structure and used in the first array.  The selector id is used in * the second.  The result value is a method implementation.  */static voidinitialize_dispatch_tables (void){  int	i;  /* Check to make sure things are in place.  */  assert (selector_record);  /* Blow away the instance and factory method records.  */  if (factory_method_record) {    for (i = 1; i <= record_entries (factory_method_record); ++i)      record_delete (record_get (i, factory_method_record));    record_delete (factory_method_record);  }  if (instance_method_record) {    for (i = 1; i <= record_entries (instance_method_record); ++i)      record_delete (record_get (i, instance_method_record));    record_delete (instance_method_record);  }  /* Reallocate the instance and factory method records.  */  factory_method_record = record_new ();  instance_method_record = record_new ();  for (i = 1; i <= record_entries (selector_record); ++i) {    record_store (record_new (), factory_method_record);    record_store (record_new (), instance_method_record);  }	  /* Fool all of the secondary records into thinking they have data.  */  for (i = 1; i <= record_entries (selector_record); ++i) {    struct record *record;    node_ptr	node;	    record = record_get (i, factory_method_record);    for (node = hash_next (module_hash_table, NULL); node;	 node = hash_next (module_hash_table, node))      record_store (NULL, record);			    record = record_get (i, instance_method_record);    for (node = hash_next (module_hash_table, NULL); node;	 node = hash_next (module_hash_table, node))      record_store (NULL, record);  }		  /* For all classes fill in the methods implemented by the class and visiable     from the class in the hierarchy.  Those methods are assigned to the     class.  */  for (i = 1; i <= record_entries (selector_record); ++i) { /* i is a sel */    node_ptr	node;	    for (node = hash_next (class_hash_table, NULL); node;	 node = hash_next (class_hash_table, node)) {      Class_t     class = node->value;      MetaClass_t meta_class = class->class_pointer;      int	  class_number = getClassNumber (class);      Method_t    method;      /* DEBUG_PRINTF ("Assignment of sel=%s, class=%s (%#x, %#x)\n", 	 sel_getName ((SEL)i), class->name,	 searchForMethodInHierarchy (class, (SEL)i),	 searchForMethodInHierarchy ((Class_t)meta_class, (SEL)i)); */      method = searchForMethodInHierarchy (class, (SEL)i);      if (method)	record_store_at (class_number, method->method_imp,			 record_get (i, instance_method_record));      assert (class_number == getClassNumber ((Class_t)class->class_pointer));      method = searchForMethodInHierarchy ((Class_t)meta_class, (SEL)i);      if (method)        record_store_at (class_number, method->method_imp,                         record_get (i, factory_method_record));    }  }}/* * This method is called by the dispatch routines when a class has not been * initialized.  This method is responsible for initializing the class.  This * is accomplished by first testing the class itself for responding to the * +initialize method.  If such a method is implemented then it is called.  * Before exit, irregardless if the class implements +initialize, the class * is marked as initialized.  */static void		initialize_class (const char *name){  Method_t	method = NULL;  Class_t	class = objc_getClass (name);  SEL		sel = sel_getUid ("initialize");	  /* The class should not be initialized at this point.  */  assert (!(class->info & CLS_INITIALIZED));  assert (!(class->class_pointer->info & CLS_INITIALIZED));  /* Search for the +initialize method.     Call it if it exists.  */  if (sel)    method = searchForMethodInList (class->class_pointer->methods,				    sel_getName (sel));  if (method) {    IMP	imp;    DEBUG_PRINTF ("Class: %s sending +%s\n", 		  name, sel_getName (sel));    imp = get_imp ((Class_t)class->class_pointer, sel);    assert (imp);    (*imp)((id)class, sel);  }  /* Mark the class as initialized.  */  class->info	|= CLS_INITIALIZED;  class->class_pointer->info	|= CLS_INITIALIZED;}/* * Silly little function that checks to make sure the class hash table is * initialized.  If it isn't initialized then do it.  */static inline voidclass_hash_init (void){  static unsigned int	init = 0;		  if (!init)    class_hash_table = hash_new (CLASS_HASH_SIZE, 				 (hash_func_type)hash_string,				 (compare_func_type)compare_strings);  init = 1;}Class_t objc_getClass (const char *name){  Class_t	class;  /* Make sure the class hash table exists.  */  class_hash_init ();  class = hash_value_for_key (class_hash_table, name);	  return class;}MetaClass_t objc_getMetaClass (const char *name){  /* Meta classes are pointed to by the class's class_pointer.     Just get the class and return its class_pointer.  */  return (objc_getClass (name))->class_pointer;}voidaddClassToHash (Class_t class){  Class_t	hClass;		  class_hash_init ();  /* Check to see if the class is already in the hash table.  */  hClass = hash_value_for_key (class_hash_table, class->name);  if (!hClass) {        /* The class isn't in the hash table.  Add the class and        assign a class number.  */    static unsigned int	class_number = 1;	    setClassNumber (class, class_number);    setClassNumber ((Class_t)class->class_pointer, class_number);    ++class_number;        hash_add (&class_hash_table, class->name, class);  }}void  debug_dump_classes (void){  node_ptr node;  int         i;  DEBUG_PRINTF ("class tables\n");  i = 0;  for (node = hash_next (class_hash_table, NULL); node;        node = hash_next (class_hash_table, node)) {    Class_t class = node->value;          DEBUG_PRINTF ("Class { /*%#x*/\n", class);    DEBUG_PRINTF ("   MetaClass_t  class_pointer = %#x\n", class->class_pointer);    DEBUG_PRINTF ("   Class_t      super_class   = %#x\n", class->super_class);    DEBUG_PRINTF ("   char         *name          = %s\n", class->name);    DEBUG_PRINTF ("   long         version       = %ld\n", class->version);    DEBUG_PRINTF ("   long         info          = %#x\n", class->info);    DEBUG_PRINTF ("   long         instance_size = %ld\n", class->instance_size);    DEBUG_PRINTF ("   IvarList_t   ivars         = %#x\n", class->ivars);    DEBUG_PRINTF ("   MethodList_t methods       = %#x\n", class->methods);    DEBUG_PRINTF ("   cache_ptr      cache         = %#x\n", class->cache);    DEBUG_PRINTF ("}[%d];\n", i++);  }      i = 0;  for (node = hash_next (class_hash_table, NULL); node;     node = hash_next (class_hash_table, node)) {    Class_t class = (Class_t)((Class_t)(node->value))->class_pointer;          DEBUG_PRINTF ("MetaClass { /*%#x*/\n", class);    DEBUG_PRINTF ("   MetaClass_t  class_pointer = %#x\n", class->class_pointer);    DEBUG_PRINTF ("   MetaClass_t  super_class   = %#x\n", class->super_class);    DEBUG_PRINTF ("   char         *name          = %s\n", class->name);    DEBUG_PRINTF ("   long         version       = %ld\n", class->version);    DEBUG_PRINTF ("   long         info          = %#x\n", class->info);    DEBUG_PRINTF ("   long         instance_size = %ld\n", class->instance_size);    DEBUG_PRINTF ("   IvarList_t   ivars         = %#x\n", class->ivars);    DEBUG_PRINTF ("   MethodList_t methods       = %#x\n", class->methods);    DEBUG_PRINTF ("   cache_ptr      cache         = %#x\n", class->cache);    DEBUG_PRINTF ("}[%d];\n", i++);  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -