mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 11:49:12 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			371 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			371 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/***********************************************************
 | 
						|
Copyright 1991-1995 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 or Corporation for National Research Initiatives or
 | 
						|
CNRI not be used in advertising or publicity pertaining to
 | 
						|
distribution of the software without specific, written prior
 | 
						|
permission.
 | 
						|
 | 
						|
While CWI is the initial source for this software, a modified version
 | 
						|
is made available by the Corporation for National Research Initiatives
 | 
						|
(CNRI) at the Internet address ftp://ftp.python.org.
 | 
						|
 | 
						|
STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
 | 
						|
REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 | 
						|
MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
 | 
						|
CENTRUM OR CNRI 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.
 | 
						|
 | 
						|
******************************************************************/
 | 
						|
 | 
						|
#ifdef SUPPORT_OBSOLETE_ACCESS /* This object type is no longer supported */
 | 
						|
 | 
						|
/* Access object implementation */
 | 
						|
 | 
						|
/* XXX TO DO LIST
 | 
						|
   - __init__ and __del__ (and all other similar methods)
 | 
						|
     should be usable even when private, not ignored
 | 
						|
*/
 | 
						|
 | 
						|
#include "allobjects.h"
 | 
						|
#include "ceval.h"
 | 
						|
#include "structmember.h"
 | 
						|
#include "modsupport.h"		/* For getargs() etc. */
 | 
						|
 | 
						|
typedef struct {
 | 
						|
	OB_HEAD
 | 
						|
	object		*ac_value;
 | 
						|
	object		*ac_owner;
 | 
						|
	typeobject	*ac_type;
 | 
						|
	int		ac_mode;
 | 
						|
} accessobject;
 | 
						|
 | 
						|
/* Forward */
 | 
						|
static int typecheck PROTO((object *, typeobject *));
 | 
						|
static int ownercheck PROTO((object *, object *, int, int));
 | 
						|
 | 
						|
object *
 | 
						|
newaccessobject(value, owner, type, mode)
 | 
						|
	object *value;
 | 
						|
	object *owner;
 | 
						|
	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;
 | 
						|
	XINCREF(owner);
 | 
						|
	ap->ac_owner = owner;
 | 
						|
	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;
 | 
						|
	return newaccessobject(ap->ac_value, ap->ac_owner,
 | 
						|
			       ap->ac_type, ap->ac_mode);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
setaccessowner(op, owner)
 | 
						|
	object *op;
 | 
						|
	object *owner;
 | 
						|
{
 | 
						|
	register accessobject *ap;
 | 
						|
	if (!is_accessobject(op))
 | 
						|
		return; /* XXX no error */
 | 
						|
	ap = (accessobject *)op;
 | 
						|
	XDECREF(ap->ac_owner);
 | 
						|
	XINCREF(owner);
 | 
						|
	ap->ac_owner = owner;
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
hasaccessvalue(op)
 | 
						|
	object *op;
 | 
						|
{	
 | 
						|
	if (!is_accessobject(op))
 | 
						|
		return 0;
 | 
						|
	return ((accessobject *)op)->ac_value != NULL;
 | 
						|
}
 | 
						|
 | 
						|
object *
 | 
						|
getaccessvalue(op, caller)
 | 
						|
	object *op;
 | 
						|
	object *caller;
 | 
						|
{
 | 
						|
	register accessobject *ap;
 | 
						|
	if (!is_accessobject(op)) {
 | 
						|
		err_badcall();
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
	ap = (accessobject *)op;
 | 
						|
	
 | 
						|
	if (!ownercheck(caller, ap->ac_owner, AC_R, ap->ac_mode)) {
 | 
						|
		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
 | 
						|
setaccessvalue(op, caller, value)
 | 
						|
	object *op;
 | 
						|
	object *caller;
 | 
						|
	object *value;
 | 
						|
{
 | 
						|
	register accessobject *ap;
 | 
						|
	if (!is_accessobject(op)) {
 | 
						|
		err_badcall();
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
	ap = (accessobject *)op;
 | 
						|
	
 | 
						|
	if (!ownercheck(caller, ap->ac_owner, AC_W, ap->ac_mode)) {
 | 
						|
		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
 | 
						|
isprivileged(caller)
 | 
						|
	object *caller;
 | 
						|
{
 | 
						|
	object *g;
 | 
						|
	static char privileged[] = "__privileged__";
 | 
						|
	if (caller != NULL && hasattr(caller, privileged))
 | 
						|
		return 1;
 | 
						|
	g = getglobals();
 | 
						|
	if (g != NULL && dictlookup(g, privileged))
 | 
						|
		return 1;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
static int
 | 
						|
ownercheck(caller, owner, access, mode)
 | 
						|
	object *caller;
 | 
						|
	object *owner;
 | 
						|
	int access;
 | 
						|
	int mode;
 | 
						|
{
 | 
						|
	int mask = AC_PUBLIC;
 | 
						|
	if (caller == owner || isprivileged(caller))
 | 
						|
		mask |= AC_PRIVATE | AC_PROTECTED;
 | 
						|
	else if (caller != NULL && owner != NULL &&
 | 
						|
		 is_classobject(owner) && is_classobject(caller) &&
 | 
						|
		 (issubclass(caller, owner) ||
 | 
						|
		  issubclass(owner, caller)))
 | 
						|
			mask |= AC_PROTECTED;
 | 
						|
	return access & mode & mask;
 | 
						|
}
 | 
						|
 | 
						|
/* Access methods */
 | 
						|
 | 
						|
static void
 | 
						|
access_dealloc(ap)
 | 
						|
	accessobject *ap;
 | 
						|
{
 | 
						|
	XDECREF(ap->ac_value);
 | 
						|
	XDECREF(ap->ac_owner);
 | 
						|
	XDECREF(ap->ac_type);
 | 
						|
	DEL(ap);
 | 
						|
}
 | 
						|
 | 
						|
#define OFF(x) offsetof(accessobject, x)
 | 
						|
 | 
						|
static struct memberlist access_memberlist[] = {
 | 
						|
	{"ac_value",	T_OBJECT,	OFF(ac_value)},
 | 
						|
	{"ac_owner",	T_OBJECT,	OFF(ac_owner)},
 | 
						|
	{"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];
 | 
						|
	char buf2[20];
 | 
						|
	char *ownername;
 | 
						|
	typeobject *type = ap->ac_type;
 | 
						|
	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;
 | 
						|
	}
 | 
						|
	sprintf(buf,
 | 
						|
	"<access object, value 0x%lx, owner %.100s, type %.100s, mode %04o>",
 | 
						|
		(long)(ap->ac_value),
 | 
						|
		ownername,
 | 
						|
		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 */
 | 
						|
	(destructor)access_dealloc, /*tp_dealloc*/
 | 
						|
	0,			/*tp_print*/
 | 
						|
	(getattrfunc)access_getattr, /*tp_getattr*/
 | 
						|
	0,			/*tp_setattr*/
 | 
						|
	0,			/*tp_compare*/
 | 
						|
	(reprfunc)access_repr, /*tp_repr*/
 | 
						|
	0,			/*tp_as_number*/
 | 
						|
	0,			/*tp_as_sequence*/
 | 
						|
	0,			/*tp_as_mapping*/
 | 
						|
	0,			/*tp_hash*/
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
/* Pseudo type objects to indicate collections of types */
 | 
						|
 | 
						|
/* 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*/
 | 
						|
};
 | 
						|
 | 
						|
#endif /* SUPPORT_OBSOLETE_ACCESS */
 |