| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | /***********************************************************
 | 
					
						
							|  |  |  | Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum, | 
					
						
							|  |  |  | Amsterdam, The Netherlands. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         All Rights Reserved | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Permission to use, copy, modify, and distribute this software and its  | 
					
						
							|  |  |  | documentation for any purpose and without fee is hereby granted,  | 
					
						
							|  |  |  | provided that the above copyright notice appear in all copies and that | 
					
						
							|  |  |  | both that copyright notice and this permission notice appear in  | 
					
						
							|  |  |  | supporting documentation, and that the names of Stichting Mathematisch | 
					
						
							|  |  |  | Centrum or CWI not be used in advertising or publicity pertaining to | 
					
						
							|  |  |  | distribution of the software without specific, written prior permission. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO | 
					
						
							|  |  |  | THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | 
					
						
							|  |  |  | FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE | 
					
						
							|  |  |  | FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 
					
						
							|  |  |  | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 
					
						
							|  |  |  | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | 
					
						
							|  |  |  | OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ******************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Access object implementation */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-06-17 12:35:49 +00:00
										 |  |  | /* XXX TO DO LIST
 | 
					
						
							|  |  |  |    - need a "super user" mechanism for debugger etc. | 
					
						
							|  |  |  |    - __init__ and __del__ (and all other similar methods) | 
					
						
							|  |  |  |      should be usable even when private, not ignored | 
					
						
							|  |  |  |    - "from foo import bar" should check access of bar | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | #include "allobjects.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "structmember.h"
 | 
					
						
							|  |  |  | #include "modsupport.h"		/* For getargs() etc. */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef struct { | 
					
						
							|  |  |  | 	OB_HEAD | 
					
						
							|  |  |  | 	object		*ac_value; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	object		*ac_owner; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	typeobject	*ac_type; | 
					
						
							|  |  |  | 	int		ac_mode; | 
					
						
							|  |  |  | } accessobject; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Forward */ | 
					
						
							|  |  |  | static int typecheck PROTO((object *, typeobject *)); | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | static int ownercheck PROTO((object *, object *, int, int)); | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | object * | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | newaccessobject(value, owner, type, mode) | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	object *value; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	object *owner; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	typeobject *type; | 
					
						
							|  |  |  | 	int mode; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	accessobject *ap; | 
					
						
							|  |  |  | 	if (!typecheck(value, type)) { | 
					
						
							|  |  |  | 		err_setstr(AccessError, | 
					
						
							|  |  |  | 		"access: initial value has inappropriate type"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ap = NEWOBJ(accessobject, &Accesstype); | 
					
						
							|  |  |  | 	if (ap == NULL) | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	XINCREF(value); | 
					
						
							|  |  |  | 	ap->ac_value = value; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	XINCREF(owner); | 
					
						
							|  |  |  | 	ap->ac_owner = owner; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	XINCREF(type); | 
					
						
							|  |  |  | 	ap->ac_type = (typeobject *)type; | 
					
						
							|  |  |  | 	ap->ac_mode = mode; | 
					
						
							|  |  |  | 	return (object *)ap; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | object * | 
					
						
							|  |  |  | cloneaccessobject(op) | 
					
						
							|  |  |  | 	object *op; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	register accessobject *ap; | 
					
						
							|  |  |  | 	if (!is_accessobject(op)) { | 
					
						
							|  |  |  | 		err_badcall(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ap = (accessobject *)op; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	return newaccessobject(ap->ac_value, ap->ac_owner, | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 			       ap->ac_type, ap->ac_mode); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | setaccessowner(op, owner) | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	object *op; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	object *owner; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	register accessobject *ap; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	if (!is_accessobject(op)) | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 		return; /* XXX no error */ | 
					
						
							|  |  |  | 	ap = (accessobject *)op; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	XDECREF(ap->ac_owner); | 
					
						
							|  |  |  | 	XINCREF(owner); | 
					
						
							|  |  |  | 	ap->ac_owner = owner; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-05-21 19:56:10 +00:00
										 |  |  | int | 
					
						
							|  |  |  | hasaccessvalue(op) | 
					
						
							|  |  |  | 	object *op; | 
					
						
							|  |  |  | {	 | 
					
						
							|  |  |  | 	if (!is_accessobject(op)) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	return ((accessobject *)op)->ac_value != NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | object * | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | getaccessvalue(op, owner) | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	object *op; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	object *owner; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	register accessobject *ap; | 
					
						
							|  |  |  | 	if (!is_accessobject(op)) { | 
					
						
							|  |  |  | 		err_badcall(); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ap = (accessobject *)op; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	if (!ownercheck(owner, ap->ac_owner, AC_R, ap->ac_mode)) { | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 		err_setstr(AccessError, "read access denied"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (ap->ac_value == NULL) { | 
					
						
							|  |  |  | 		err_setstr(AccessError, "no current value"); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	INCREF(ap->ac_value); | 
					
						
							|  |  |  | 	return ap->ac_value; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | setaccessvalue(op, owner, value) | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	object *op; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	object *owner; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	object *value; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	register accessobject *ap; | 
					
						
							|  |  |  | 	if (!is_accessobject(op)) { | 
					
						
							|  |  |  | 		err_badcall(); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ap = (accessobject *)op; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	if (!ownercheck(owner, ap->ac_owner, AC_W, ap->ac_mode)) { | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 		err_setstr(AccessError, "write access denied"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!typecheck(value, ap->ac_type)) { | 
					
						
							|  |  |  | 		err_setstr(AccessError, "assign value of inappropriate type"); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (value == NULL) { /* Delete it */ | 
					
						
							|  |  |  | 		if (ap->ac_value == NULL) { | 
					
						
							|  |  |  | 			err_setstr(AccessError, "no current value"); | 
					
						
							|  |  |  | 			return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		DECREF(ap->ac_value); | 
					
						
							|  |  |  | 		ap->ac_value = NULL; | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	XDECREF(ap->ac_value); | 
					
						
							|  |  |  | 	INCREF(value); | 
					
						
							|  |  |  | 	ap->ac_value = value; | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | typecheck(value, type) | 
					
						
							|  |  |  | 	object *value; | 
					
						
							|  |  |  | 	typeobject *type; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	object *x; | 
					
						
							|  |  |  | 	if (value == NULL || type == NULL) | 
					
						
							|  |  |  | 		return 1; /* No check */ | 
					
						
							|  |  |  | 	if (value->ob_type == type) | 
					
						
							|  |  |  | 		return 1; /* Exact match */ | 
					
						
							|  |  |  | 	if (type == &Anynumbertype) { | 
					
						
							|  |  |  | 		if (value->ob_type->tp_as_number == NULL) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		if (!is_instanceobject(value)) | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		/* For instances, make sure it really looks like a number */ | 
					
						
							|  |  |  | 		x = getattr(value, "__sub__"); | 
					
						
							|  |  |  | 		if (x == NULL) { | 
					
						
							|  |  |  | 			err_clear(); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		DECREF(x); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type == &Anysequencetype) { | 
					
						
							|  |  |  | 		if (value->ob_type->tp_as_sequence == NULL) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		if (!is_instanceobject(value)) | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		/* For instances, make sure it really looks like a sequence */ | 
					
						
							|  |  |  | 		x = getattr(value, "__getslice__"); | 
					
						
							|  |  |  | 		if (x == NULL) { | 
					
						
							|  |  |  | 			err_clear(); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		DECREF(x); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (type == &Anymappingtype) { | 
					
						
							|  |  |  | 		if (value->ob_type->tp_as_mapping == NULL) | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		if (!is_instanceobject(value)) | 
					
						
							|  |  |  | 			return 1; | 
					
						
							|  |  |  | 		/* For instances, make sure it really looks like a mapping */ | 
					
						
							|  |  |  | 		x = getattr(value, "__getitem__"); | 
					
						
							|  |  |  | 		if (x == NULL) { | 
					
						
							|  |  |  | 			err_clear(); | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		DECREF(x); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | ownercheck(caller, owner, access, mode) | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	object *caller; | 
					
						
							|  |  |  | 	object *owner; | 
					
						
							|  |  |  | 	int access; | 
					
						
							|  |  |  | 	int mode; | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	int mask = AC_PUBLIC; | 
					
						
							|  |  |  | 	if (owner != NULL) { | 
					
						
							|  |  |  | 		if (caller == owner) | 
					
						
							|  |  |  | 			mask |= AC_PRIVATE | AC_PROTECTED; | 
					
						
							|  |  |  | 		else if (is_classobject(owner) && issubclass(caller, owner)) | 
					
						
							|  |  |  | 			mask |= AC_PROTECTED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return access & mode & mask; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Access methods */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | access_dealloc(ap) | 
					
						
							|  |  |  | 	accessobject *ap; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	XDECREF(ap->ac_value); | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	XDECREF(ap->ac_owner); | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	XDECREF(ap->ac_type); | 
					
						
							|  |  |  | 	DEL(ap); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define OFF(x) offsetof(accessobject, x)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct memberlist access_memberlist[] = { | 
					
						
							|  |  |  | 	{"ac_value",	T_OBJECT,	OFF(ac_value)}, | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	{"ac_owner",	T_OBJECT,	OFF(ac_owner)}, | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	{"ac_type",	T_OBJECT,	OFF(ac_type)}, | 
					
						
							|  |  |  | 	{"ac_mode",	T_INT,		OFF(ac_mode)}, | 
					
						
							|  |  |  | 	{NULL}	/* Sentinel */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static object * | 
					
						
							|  |  |  | access_getattr(ap, name) | 
					
						
							|  |  |  | 	accessobject *ap; | 
					
						
							|  |  |  | 	char *name; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return getmember((char *)ap, access_memberlist, name); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static object * | 
					
						
							|  |  |  | access_repr(ap) | 
					
						
							|  |  |  | 	accessobject *ap; | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	char buf[300]; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	char buf2[20]; | 
					
						
							|  |  |  | 	char *ownername; | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 	typeobject *type = ap->ac_type; | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	if (is_classobject(ap->ac_owner)) { | 
					
						
							|  |  |  | 		ownername = | 
					
						
							|  |  |  | 			getstringvalue(((classobject *)ap->ac_owner)->cl_name); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		sprintf(buf2, "0x%lx", (long)ap->ac_owner); | 
					
						
							|  |  |  | 		ownername = buf2; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											1993-05-21 19:56:10 +00:00
										 |  |  | 	sprintf(buf, | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 	"<access object, value 0x%lx, owner %.100s, type %.100s, mode %04o>", | 
					
						
							| 
									
										
										
										
											1993-05-21 19:56:10 +00:00
										 |  |  | 		(long)(ap->ac_value), | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 		ownername, | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 		type ? type->tp_name : "-", | 
					
						
							|  |  |  | 		ap->ac_mode); | 
					
						
							|  |  |  | 	return newstringobject(buf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typeobject Accesstype = { | 
					
						
							|  |  |  | 	OB_HEAD_INIT(&Typetype) | 
					
						
							|  |  |  | 	0,			/*ob_size*/ | 
					
						
							|  |  |  | 	"access",		/*tp_name*/ | 
					
						
							|  |  |  | 	sizeof(accessobject),	/*tp_size*/ | 
					
						
							|  |  |  | 	0,			/*tp_itemsize*/ | 
					
						
							|  |  |  | 	/* methods */ | 
					
						
							|  |  |  | 	access_dealloc,		/*tp_dealloc*/ | 
					
						
							|  |  |  | 	0,			/*tp_print*/ | 
					
						
							|  |  |  | 	access_getattr,		/*tp_getattr*/ | 
					
						
							|  |  |  | 	0,			/*tp_setattr*/ | 
					
						
							|  |  |  | 	0,			/*tp_compare*/ | 
					
						
							|  |  |  | 	access_repr,		/*tp_repr*/ | 
					
						
							|  |  |  | 	0,			/*tp_as_number*/ | 
					
						
							|  |  |  | 	0,			/*tp_as_sequence*/ | 
					
						
							|  |  |  | 	0,			/*tp_as_mapping*/ | 
					
						
							|  |  |  | 	0,			/*tp_hash*/ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1993-05-25 09:38:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Pseudo type objects to indicate collections of types */ | 
					
						
							| 
									
										
										
										
											1993-05-20 14:24:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* XXX This should be replaced by a more general "subclassing"
 | 
					
						
							|  |  |  |    XXX mechanism for type objects... */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typeobject Anynumbertype = { | 
					
						
							|  |  |  | 	OB_HEAD_INIT(&Typetype) | 
					
						
							|  |  |  | 	0,			/*ob_size*/ | 
					
						
							|  |  |  | 	"*number*",		/*tp_name*/ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* XXX Should really distinguish mutable and immutable sequences as well */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typeobject Anysequencetype = { | 
					
						
							|  |  |  | 	OB_HEAD_INIT(&Typetype) | 
					
						
							|  |  |  | 	0,			/*ob_size*/ | 
					
						
							|  |  |  | 	"*sequence*",		/*tp_name*/ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typeobject Anymappingtype = { | 
					
						
							|  |  |  | 	OB_HEAD_INIT(&Typetype) | 
					
						
							|  |  |  | 	0,			/*ob_size*/ | 
					
						
							|  |  |  | 	"*mapping*",		/*tp_name*/ | 
					
						
							|  |  |  | }; |