From patchwork Tue Oct 12 22:01:41 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nicola Pero X-Patchwork-Id: 67627 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B61B4B6EED for ; Wed, 13 Oct 2010 09:02:02 +1100 (EST) Received: (qmail 31062 invoked by alias); 12 Oct 2010 22:02:00 -0000 Received: (qmail 31047 invoked by uid 22791); 12 Oct 2010 22:01:57 -0000 X-SWARE-Spam-Status: No, hits=-1.1 required=5.0 tests=AWL, BAYES_00, SARE_SUB_ENC_UTF8, TW_BJ, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from fencepost.gnu.org (HELO fencepost.gnu.org) (140.186.70.10) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 12 Oct 2010 22:01:50 +0000 Received: from eggs.gnu.org ([140.186.70.92]:59600) by fencepost.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1P5muq-0005XD-AK for gcc-patches@gnu.org; Tue, 12 Oct 2010 18:01:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1P5muk-0000hR-Ew for gcc-patches@gnu.org; Tue, 12 Oct 2010 18:01:48 -0400 Received: from smtp121.iad.emailsrvr.com ([207.97.245.121]:45108) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1P5muk-0000hM-As for gcc-patches@gnu.org; Tue, 12 Oct 2010 18:01:42 -0400 Received: from relay22.relay.iad.mlsrvr.com (localhost [127.0.0.1]) by relay22.relay.iad.mlsrvr.com (SMTP Server) with ESMTP id BC6C11B53F7 for ; Tue, 12 Oct 2010 18:01:41 -0400 (EDT) Received: from dynamic9.wm-web.iad.mlsrvr.com (dynamic9.wm-web.iad.mlsrvr.com [192.168.2.216]) by relay22.relay.iad.mlsrvr.com (SMTP Server) with ESMTP id B79F01B53F1 for ; Tue, 12 Oct 2010 18:01:41 -0400 (EDT) Received: from meta-innovation.com (localhost [127.0.0.1]) by dynamic9.wm-web.iad.mlsrvr.com (Postfix) with ESMTP id A94BF320088 for ; Tue, 12 Oct 2010 18:01:41 -0400 (EDT) Received: by www2.webmail.us (Authenticated sender: nicola.pero@meta-innovation.com, from: nicola.pero@meta-innovation.com) with HTTP; Wed, 13 Oct 2010 00:01:41 +0200 (CEST) Date: Wed, 13 Oct 2010 00:01:41 +0200 (CEST) Subject: =?UTF-8?Q?libobjc=20-=20more=20modern=20Objective-C=20runtime=20API=20(5?= =?UTF-8?Q?)=20?= From: "Nicola Pero" To: "gcc-patches@gnu.org" MIME-Version: 1.0 X-Type: plain Message-ID: <1286920901.692114680@192.168.2.228> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Another chunk of "modern" runtime functions. Committed to trunk. Thanks 2010-10-12 Nicola Pero * Makefile.in (C_SOURCE_FILES): Added methods.c. * encoding.c (method_getNumberOfArguments): New. (method_get_number_of_arguments): Call method_getNumberOfArguments. * ivars.c (ivar_getName): Check for NULL variable argument. (ivar_getOffset): Check for NULL variable argument. (ivar_getTypeEncoding): Check for NULL variable argument. (class_copyIvarList): New. * methods.c: New. * protocols.c (class_copyProtocolList): Check for Nil class_ argument. * sendmsg.c: Use 'struct objc_method *' instead of Method_t, and 'struct objc_method_list *' instead of MethodList_t. (class_getMethodImplementation): New. (class_respondsToSelector): New. (class_getInstanceMethod): New. (class_getClassMethod): New. * objc/runtime.h: Updated comments. (class_copyIvarList): New. (class_getInstanceMethod): New. (class_getClassMethod): New. (class_getMethodImplementation): New. (class_respondsToSelector): New. (method_getName): New. (method_getImplementation): New. (method_getTypeEncoding): New. (class_copyMethodList): New. (method_getNumberOfArguments): New. Index: sendmsg.c =================================================================== --- sendmsg.c (revision 165396) +++ sendmsg.c (working copy) @@ -1,6 +1,6 @@ /* GNU Objective C Runtime message lookup Copyright (C) 1993, 1995, 1996, 1997, 1998, - 2001, 2002, 2004, 2009 Free Software Foundation, Inc. + 2001, 2002, 2004, 2009, 2010 Free Software Foundation, Inc. Contributed by Kresten Krab Thorup This file is part of GCC. @@ -91,8 +91,8 @@ static __big static id #endif __objc_block_forward (id, SEL, ...); -static Method_t search_for_method_in_hierarchy (Class class, SEL sel); -Method_t search_for_method_in_list (MethodList_t list, SEL op); +static struct objc_method * search_for_method_in_hierarchy (Class class, SEL sel); +struct objc_method * search_for_method_in_list (struct objc_method_list * list, SEL op); id nil_method (id, SEL); /* Given a selector, return the proper forwarding implementation. */ @@ -193,11 +193,22 @@ get_imp (Class class, SEL sel) return res; } +/* The new name of get_imp(). */ +IMP +class_getMethodImplementation (Class class_, SEL selector) +{ + if (class_ == Nil || selector == NULL) + return NULL; + + /* get_imp is inlined, so we're good. */ + return get_imp (class_, selector); +} + /* Given a method, return its implementation. */ IMP -method_get_imp (Method_t method) +method_get_imp (struct objc_method * method) { - return (method != (Method_t)0) ? method->method_imp : (IMP)0; + return (method != (struct objc_method *)0) ? method->method_imp : (IMP)0; } /* Query if an object can respond to a selector, returns YES if the @@ -225,6 +236,30 @@ __objc_responds_to (id object, SEL sel) return (res != 0); } +BOOL +class_respondsToSelector (Class class_, SEL selector) +{ + void *res; + + if (class_ == Nil || selector == NULL) + return NO; + + /* Install dispatch table if need be */ + if (class_->dtable == __objc_uninstalled_dtable) + { + objc_mutex_lock (__objc_runtime_mutex); + if (class_->dtable == __objc_uninstalled_dtable) + { + __objc_install_dispatch_table_for_class (class_); + } + objc_mutex_unlock (__objc_runtime_mutex); + } + + /* Get the method from the dispatch table */ + res = sarray_get_safe (class_->dtable, (size_t) selector->sel_id); + return (res != 0); +} + /* This is the lookup function. All entries in the table are either a valid method *or* zero. If zero then either the dispatch table needs to be installed or it doesn't exist and forwarding is attempted. */ @@ -374,11 +409,11 @@ __objc_send_initialize (Class class) { SEL op = sel_register_name ("initialize"); IMP imp = 0; - MethodList_t method_list = class->class_pointer->methods; + struct objc_method_list * method_list = class->class_pointer->methods; while (method_list) { int i; - Method_t method; + struct objc_method * method; for (i = 0; i < method_list->method_count; i++) { method = &(method_list->method_list[i]); @@ -409,7 +444,7 @@ __objc_send_initialize (Class class) method nothing is guaranteed about what method will be used. Assumes that __objc_runtime_mutex is locked down. */ static void -__objc_install_methods_in_dtable (Class class, MethodList_t method_list) +__objc_install_methods_in_dtable (Class class, struct objc_method_list * method_list) { int i; @@ -421,7 +456,7 @@ static void for (i = 0; i < method_list->method_count; i++) { - Method_t method = &(method_list->method_list[i]); + struct objc_method * method = &(method_list->method_list[i]); sarray_at_put_safe (class->dtable, (sidx) method->method_name->sel_id, method->method_imp); @@ -492,7 +527,7 @@ __objc_update_dispatch_table_for_class (Class clas methods installed right away, and their selectors are made into SEL's by the function __objc_register_selectors_from_class. */ void -class_add_method_list (Class class, MethodList_t list) +class_add_method_list (Class class, struct objc_method_list * list) { /* Passing of a linked list is not allowed. Do multiple calls. */ assert (! list->method_next); @@ -507,27 +542,44 @@ void __objc_update_dispatch_table_for_class (class); } -Method_t +struct objc_method * class_get_instance_method (Class class, SEL op) { return search_for_method_in_hierarchy (class, op); } -Method_t +struct objc_method * class_get_class_method (MetaClass class, SEL op) { return search_for_method_in_hierarchy (class, op); } +struct objc_method * +class_getInstanceMethod (Class class_, SEL selector) +{ + if (class_ == Nil || selector == NULL) + return NULL; + return search_for_method_in_hierarchy (class_, selector); +} + +struct objc_method * +class_getClassMethod (Class class_, SEL selector) +{ + if (class_ == Nil || selector == NULL) + return NULL; + + return search_for_method_in_hierarchy (class_->class_pointer, + selector); +} + /* Search for a method starting from the current class up its hierarchy. Return a pointer to the method's method structure if found. NULL otherwise. */ - -static Method_t +static struct objc_method * search_for_method_in_hierarchy (Class cls, SEL sel) { - Method_t method = NULL; + struct objc_method * method = NULL; Class class; if (! sel_is_mapped (sel)) @@ -546,10 +598,10 @@ search_for_method_in_hierarchy (Class cls, SEL sel /* Given a linked list of method and a method's name. Search for the named method's method structure. Return a pointer to the method's method structure if found. NULL otherwise. */ -Method_t -search_for_method_in_list (MethodList_t list, SEL op) +struct objc_method * +search_for_method_in_list (struct objc_method_list * list, SEL op) { - MethodList_t method_list = list; + struct objc_method_list * method_list = list; if (! sel_is_mapped (op)) return NULL; @@ -562,7 +614,7 @@ search_for_method_in_hierarchy (Class cls, SEL sel /* Search the method list. */ for (i = 0; i < method_list->method_count; ++i) { - Method_t method = &method_list->method_list[i]; + struct objc_method * method = &method_list->method_list[i]; if (method->method_name) if (method->method_name->sel_id == op->sel_id) Index: Makefile.in =================================================================== --- Makefile.in (revision 165396) +++ Makefile.in (working copy) @@ -173,6 +173,7 @@ C_SOURCE_FILES = \ init.c \ ivars.c \ memory.c \ + methods.c \ nil_method.c \ objc-foreach.c \ objc-sync.c \ Index: protocols.c =================================================================== --- protocols.c (revision 165396) +++ protocols.c (working copy) @@ -211,6 +211,13 @@ class_copyProtocolList (Class class_, unsigned int Protocol **returnValue = NULL; struct objc_protocol_list* proto_list; + if (class_ == Nil) + { + if (numberOfReturnedProtocols) + *numberOfReturnedProtocols = 0; + return NULL; + } + /* Lock the runtime mutex because the class protocols may be concurrently modified. */ objc_mutex_lock (__objc_runtime_mutex); Index: encoding.c =================================================================== --- encoding.c (revision 165396) +++ encoding.c (working copy) @@ -797,24 +797,41 @@ objc_skip_argspec (const char *type) return type; } -/* - Return the number of arguments that the method MTH expects. - Note that all methods need two implicit arguments `self' and - `_cmd'. -*/ -int -method_get_number_of_arguments (struct objc_method *mth) +unsigned int +method_getNumberOfArguments (struct objc_method *method) { - int i = 0; - const char *type = mth->method_types; - while (*type) + if (method == NULL) + return 0; + else { - type = objc_skip_argspec (type); - i += 1; + unsigned int i = 0; + const char *type = method->method_types; + while (*type) + { + type = objc_skip_argspec (type); + i += 1; + } + + if (i == 0) + { + /* This could only happen if method_types is invalid; in + that case, return 0. */ + return 0; + } + else + { + /* Remove the return type. */ + return (i - 1); + } } - return i - 1; } +int +method_get_number_of_arguments (struct objc_method *mth) +{ + return method_getNumberOfArguments (mth); +} + /* Return the size of the argument block needed on the stack to invoke the method MTH. This may be zero, if all arguments are passed in Index: methods.c =================================================================== --- methods.c (revision 0) +++ methods.c (revision 0) @@ -0,0 +1,114 @@ +/* GNU Objective C Runtime method related functions. + Copyright (C) 2010 Free Software Foundation, Inc. + Contributed by Nicola Pero + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation; either version 3, or (at your option) any later version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "objc-private/common.h" +#include "objc/runtime.h" +#include "objc-private/module-abi-8.h" /* For runtime structures. */ +#include "objc/thr.h" +#include "objc-private/runtime.h" /* For __objc_runtime_mutex. */ +#include /* For malloc. */ + +SEL method_getName (struct objc_method * method) +{ + if (method == NULL) + return NULL; + + return method->method_name; +} + +const char * method_getTypeEncoding (struct objc_method * method) +{ + if (method == NULL) + return NULL; + + return method->method_types; +} + +IMP method_getImplementation (struct objc_method * method) +{ + if (method == NULL) + return NULL; + + return method->method_imp; +} + +struct objc_method ** class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods) +{ + unsigned int count = 0; + struct objc_method **returnValue = NULL; + struct objc_method_list* method_list; + + if (class_ == Nil) + { + if (numberOfReturnedMethods) + *numberOfReturnedMethods = 0; + return NULL; + } + + /* Lock the runtime mutex because the class methods may be + concurrently modified. */ + objc_mutex_lock (__objc_runtime_mutex); + + /* Count how many methods we have. */ + method_list = class_->methods; + + while (method_list) + { + count = count + method_list->method_count; + method_list = method_list->method_next; + } + + if (count != 0) + { + unsigned int i = 0; + + /* Allocate enough memory to hold them. */ + returnValue + = (struct objc_method **)(malloc (sizeof (struct objc_method *) + * (count + 1))); + + /* Copy the methods. */ + method_list = class_->methods; + + while (method_list) + { + int j; + for (j = 0; j < method_list->method_count; j++) + { + returnValue[i] = &(method_list->method_list[j]); + i++; + } + method_list = method_list->method_next; + } + + returnValue[i] = NULL; + } + + objc_mutex_unlock (__objc_runtime_mutex); + + if (numberOfReturnedMethods) + *numberOfReturnedMethods = count; + + return returnValue; +} Index: ChangeLog =================================================================== --- ChangeLog (revision 165396) +++ ChangeLog (working copy) @@ -1,5 +1,36 @@ 2010-10-12 Nicola Pero + * Makefile.in (C_SOURCE_FILES): Added methods.c. + * encoding.c (method_getNumberOfArguments): New. + (method_get_number_of_arguments): Call + method_getNumberOfArguments. + * ivars.c (ivar_getName): Check for NULL variable argument. + (ivar_getOffset): Check for NULL variable argument. + (ivar_getTypeEncoding): Check for NULL variable argument. + (class_copyIvarList): New. + * methods.c: New. + * protocols.c (class_copyProtocolList): Check for Nil class_ + argument. + * sendmsg.c: Use 'struct objc_method *' instead of Method_t, and + 'struct objc_method_list *' instead of MethodList_t. + (class_getMethodImplementation): New. + (class_respondsToSelector): New. + (class_getInstanceMethod): New. + (class_getClassMethod): New. + * objc/runtime.h: Updated comments. + (class_copyIvarList): New. + (class_getInstanceMethod): New. + (class_getClassMethod): New. + (class_getMethodImplementation): New. + (class_respondsToSelector): New. + (method_getName): New. + (method_getImplementation): New. + (method_getTypeEncoding): New. + (class_copyMethodList): New. + (method_getNumberOfArguments): New. + +2010-10-12 Nicola Pero + * class.c: Include objc/runtime.h and objc-private/module-abi-8.h instead of objc/objc-api.h. (objc_get_unknown_class_handler): Do not define. Index: ivars.c =================================================================== --- ivars.c (revision 165396) +++ ivars.c (working copy) @@ -26,8 +26,8 @@ see the files COPYING3 and COPYING.RUNTIME respect #include "objc/runtime.h" #include "objc-private/module-abi-8.h" /* For runtime structures */ #include "objc/thr.h" -#include "objc-private/runtime.h" /* the kitchen sink */ -#include /* For strcmp */ +#include "objc-private/runtime.h" /* the kitchen sink */ +#include /* For strcmp */ struct objc_ivar * class_getInstanceVariable (Class class_, const char *name) @@ -157,15 +157,74 @@ void object_setIvar (id object, struct objc_ivar * const char * ivar_getName (struct objc_ivar * variable) { + if (variable == NULL) + return NULL; + return variable->ivar_name; } ptrdiff_t ivar_getOffset (struct objc_ivar * variable) { + if (variable == NULL) + return 0; + return (ptrdiff_t)(variable->ivar_offset); } const char * ivar_getTypeEncoding (struct objc_ivar * variable) { + if (variable == NULL) + return NULL; + return variable->ivar_type; } + +struct objc_ivar ** class_copyIvarList (Class class_, unsigned int *numberOfReturnedIvars) +{ + unsigned int count = 0; + struct objc_ivar **returnValue = NULL; + struct objc_ivar_list* ivar_list; + + if (class_ == Nil) + { + if (numberOfReturnedIvars) + *numberOfReturnedIvars = 0; + return NULL; + } + + /* TODO: We do not need to lock the runtime mutex if the class has + been registered with the runtime, since the instance variable + list can not change after the class is registered. The only case + where the lock may be useful if the class is still being created + using objc_allocateClassPair(), but has not been registered using + objc_registerClassPair() yet. I'm not even sure that is + allowed. */ + objc_mutex_lock (__objc_runtime_mutex); + + /* Count how many ivars we have. */ + ivar_list = class_->ivars; + count = ivar_list->ivar_count; + + if (count != 0) + { + unsigned int i = 0; + + /* Allocate enough memory to hold them. */ + returnValue = (struct objc_ivar **)(malloc (sizeof (struct objc_ivar *) * (count + 1))); + + /* Copy the ivars. */ + for (i = 0; i < count; i++) + { + returnValue[i] = &(ivar_list->ivar_list[i]); + } + + returnValue[i] = NULL; + } + + objc_mutex_unlock (__objc_runtime_mutex); + + if (numberOfReturnedIvars) + *numberOfReturnedIvars = count; + + return returnValue; +} Index: objc/runtime.h =================================================================== --- objc/runtime.h (revision 165396) +++ objc/runtime.h (working copy) @@ -284,17 +284,28 @@ objc_EXPORT id object_getIvar (id object, Ivar var object_setInstanceVariable. */ objc_EXPORT void object_setIvar (id object, Ivar variable, id value); -/* Return the name of the instance variable. */ +/* Return the name of the instance variable. Return NULL if + 'variable' is NULL. */ objc_EXPORT const char * ivar_getName (Ivar variable); /* Return the offset of the instance variable from the start of the - object data. */ + object data. Return 0 if 'variable' is NULL. */ objc_EXPORT ptrdiff_t ivar_getOffset (Ivar variable); -/* Return the type encoding of the variable. */ +/* Return the type encoding of the variable. Return NULL if + 'variable' is NULL. */ objc_EXPORT const char * ivar_getTypeEncoding (Ivar variable); +/* Return all the instance variables of the class. The return value + of the function is a pointer to an area, allocated with malloc(), + that contains all the instance variables of the class. It does not + include instance variables of superclasses. The list is terminated + by NULL. Optionally, if you pass a non-NULL + 'numberOfReturnedIvars' pointer, the unsigned int that it points to + will be filled with the number of instance variables returned. */ +objc_EXPORT Ivar * class_copyIvarList (Class class_, unsigned int *numberOfReturnedIvars); + /** Implementation: the following functions are in class.c. */ /* Compatibility Note: The Apple/NeXT runtime does not have @@ -412,6 +423,84 @@ objc_EXPORT void class_setVersion (Class class_, i objc_EXPORT size_t class_getInstanceSize (Class class_); +/** Implementation: the following functions are in sendmsg.c. */ + +/* Return the instance method with selector 'selector' of class + 'class_', or NULL if the class (or one of its superclasses) does + not implement the method. Return NULL if class_ is Nil or selector + is NULL. */ +objc_EXPORT Method class_getInstanceMethod (Class class_, SEL selector); + +/* Return the class method with selector 'selector' of class 'class_', + or NULL if the class (or one of its superclasses) does not + implement the method. Return NULL if class_ is Nil or selector is + NULL. */ +objc_EXPORT Method class_getClassMethod (Class class_, SEL selector); + +/* Return the IMP (pointer to the function implementing a method) for + the instance method with selector 'selector' in class 'class_'. + This is the same routine that is used while messaging, and should + be very fast. Note that you most likely would need to cast the + return function pointer to a function pointer with the appropriate + arguments and return type before calling it. To get a class + method, you can pass the meta-class as the class_ argument (ie, use + class_getMethodImplementation (object_getClass (class_), + selector)). Return NULL if class_ is Nil or selector is NULL. */ +objc_EXPORT IMP class_getMethodImplementation (Class class_, SEL selector); + +/* Compatibility Note: the Apple/NeXT runtime has the function + class_getMethodImplementation_stret () which currently does not + exist on the GNU runtime because the messaging implementation is + different. */ + +/* Return YES if class 'class_' has an instance method implementing + selector 'selector', and NO if not. Return NO if class_ is Nil or + selector is NULL. If you need to check a class method, use the + meta-class as the class_ argument (ie, use class_respondsToSelector + (object_getClass (class_), selector)). */ +objc_EXPORT BOOL class_respondsToSelector (Class class_, SEL selector); + + +/** Implementation: the following functions are in methods.c. */ + +/* Return the selector for method 'method'. Return NULL if 'method' + is NULL. + + This function is misnamed; it should be called + 'method_getSelector'. To get the actual name, get the selector, + then the name from the selector (ie, use sel_getName + (method_getName (method))). */ +objc_EXPORT SEL method_getName (Method method); + +/* Return the IMP of the method. Return NULL if 'method' is NULL. */ +objc_EXPORT IMP method_getImplementation (Method method); + +/* Return the type encoding of the method. Return NULL if 'method' is + NULL. */ +objc_EXPORT const char * method_getTypeEncoding (Method method); + +/* Return all the instance methods of the class. The return value of + the function is a pointer to an area, allocated with malloc(), that + contains all the instance methods of the class. It does not + include instance methods of superclasses. The list is terminated + by NULL. Optionally, if you pass a non-NULL + 'numberOfReturnedMethods' pointer, the unsigned int that it points + to will be filled with the number of instance methods returned. To + get the list of class methods, pass the meta-class in the 'class_' + argument, (ie, use class_copyMethodList (object_getClass (class_), + &numberOfReturnedMethods)). */ +objc_EXPORT Method * class_copyMethodList (Class class_, unsigned int *numberOfReturnedMethods); + + +/** Implementation: the following functions are in encoding.c. */ + +/* Return the number of arguments that the method 'method' expects. + Note that all methods need two implicit arguments ('self' for the + receiver, and '_cmd' for the selector). Return 0 if 'method' is + NULL. */ +objc_EXPORT unsigned int method_getNumberOfArguments (Method method); + + /** Implementation: the following functions are in protocols.c. */ /* Return the protocol with name 'name', or nil if it the protocol is