mirror of https://github.com/python/cpython
Access checks now work, at least for instance data (not for methods
yet). The class is now passed to eval_code and stored in the current frame. It is also stored in instance method objects. An "unbound" instance method is now returned when a function is retrieved through "classname.funcname", which when called passes the class to eval_code.
This commit is contained in:
parent
25831652fd
commit
81daa32c15
|
@ -0,0 +1,54 @@
|
|||
/***********************************************************
|
||||
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 interface */
|
||||
|
||||
/* Access mode bits (note similarity with UNIX permissions) */
|
||||
#define AC_R 0444
|
||||
#define AC_W 0222
|
||||
|
||||
#define AC_PRIVATE 0700
|
||||
#define AC_R_PRIVATE 0400
|
||||
#define AC_W_PRIVATE 0200
|
||||
|
||||
#define AC_PROTECTED 0070
|
||||
#define AC_R_PROTECTED 0040
|
||||
#define AC_W_PROTECTED 0020
|
||||
|
||||
#define AC_PUBLIC 0007
|
||||
#define AC_R_PUBLIC 0004
|
||||
#define AC_W_PUBLIC 0002
|
||||
|
||||
extern typeobject Accesstype;
|
||||
|
||||
#define is_accessobject(v) ((v)->ob_type == &Accesstype)
|
||||
|
||||
object *newaccessobject PROTO((object *, object *, typeobject *, int));
|
||||
object *getaccessvalue PROTO((object *, object *));
|
||||
int setaccessvalue PROTO((object *, object *, object *));
|
||||
|
||||
void setaccessowner PROTO((object *, object *));
|
||||
object *cloneaccessobject PROTO((object *));
|
||||
|
||||
extern typeobject Anynumbertype, Anysequencetype, Anymappingtype;
|
|
@ -28,6 +28,7 @@ object *call_object PROTO((object *, object *));
|
|||
|
||||
object *getglobals PROTO((void));
|
||||
object *getlocals PROTO((void));
|
||||
object *getclass PROTO((void));
|
||||
void mergelocals PROTO((void));
|
||||
|
||||
void printtraceback PROTO((object *));
|
||||
|
|
|
@ -30,6 +30,13 @@ It should be possible to use other object types as base classes,
|
|||
but currently it isn't. We'll see if we can fix that later, sigh...
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
OB_HEAD
|
||||
object *cl_bases; /* A tuple of class objects */
|
||||
object *cl_dict; /* A dictionary */
|
||||
object *cl_name; /* A string */
|
||||
} classobject;
|
||||
|
||||
extern typeobject Classtype, Instancetype, Instancemethodtype;
|
||||
|
||||
#define is_classobject(op) ((op)->ob_type == &Classtype)
|
||||
|
@ -38,9 +45,12 @@ extern typeobject Classtype, Instancetype, Instancemethodtype;
|
|||
|
||||
extern object *newclassobject PROTO((object *, object *, object *));
|
||||
extern object *newinstanceobject PROTO((object *, object *));
|
||||
extern object *newinstancemethodobject PROTO((object *, object *));
|
||||
extern object *newinstancemethodobject PROTO((object *, object *, object *));
|
||||
|
||||
extern object *instancemethodgetfunc PROTO((object *));
|
||||
extern object *instancemethodgetself PROTO((object *));
|
||||
extern object *instancemethodgetclass PROTO((object *));
|
||||
|
||||
extern object *instance_convert PROTO((object *, char *));
|
||||
|
||||
extern int issubclass PROTO((object *, object *));
|
||||
|
|
|
@ -24,4 +24,5 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
|
||||
/* Interface to execute compiled code */
|
||||
|
||||
object *eval_code PROTO((codeobject *, object *, object *, object *));
|
||||
object *eval_code
|
||||
PROTO((codeobject *, object *, object *, object *, object *));
|
||||
|
|
|
@ -36,6 +36,7 @@ typedef struct _frame {
|
|||
codeobject *f_code; /* code segment */
|
||||
object *f_globals; /* global symbol table (dictobject) */
|
||||
object *f_locals; /* local symbol table (dictobject) */
|
||||
object *f_class; /* class context (classobject or NULL) */
|
||||
object *f_fastlocals; /* fast local variables (listobject) */
|
||||
object *f_localmap; /* local variable names (dictobject) */
|
||||
object **f_valuestack; /* malloc'ed array */
|
||||
|
@ -55,7 +56,7 @@ extern typeobject Frametype;
|
|||
#define is_frameobject(op) ((op)->ob_type == &Frametype)
|
||||
|
||||
frameobject * newframeobject PROTO(
|
||||
(frameobject *, codeobject *, object *, object *, int, int));
|
||||
(frameobject *, codeobject *, object *, object *, object *, int, int));
|
||||
|
||||
|
||||
/* The rest of the interface is specific for frame objects */
|
||||
|
|
|
@ -0,0 +1,320 @@
|
|||
/***********************************************************
|
||||
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 */
|
||||
|
||||
#include "allobjects.h"
|
||||
|
||||
#include "structmember.h"
|
||||
#include "modsupport.h" /* For getargs() etc. */
|
||||
|
||||
typedef struct {
|
||||
OB_HEAD
|
||||
object *ac_value;
|
||||
object *ac_class;
|
||||
typeobject *ac_type;
|
||||
int ac_mode;
|
||||
} accessobject;
|
||||
|
||||
/* Forward */
|
||||
static int typecheck PROTO((object *, typeobject *));
|
||||
static int classcheck PROTO((object *, object *, int, int));
|
||||
|
||||
object *
|
||||
newaccessobject(value, class, type, mode)
|
||||
object *value;
|
||||
object *class;
|
||||
typeobject *type;
|
||||
int mode;
|
||||
{
|
||||
accessobject *ap;
|
||||
if (class != NULL && !is_classobject(class)) {
|
||||
err_badcall();
|
||||
return NULL;
|
||||
}
|
||||
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(class);
|
||||
ap->ac_class = class;
|
||||
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_class,
|
||||
ap->ac_type, ap->ac_mode);
|
||||
}
|
||||
|
||||
void
|
||||
setaccessowner(op, class)
|
||||
object *op;
|
||||
object *class;
|
||||
{
|
||||
register accessobject *ap;
|
||||
if (!is_accessobject(op) || class != NULL && !is_classobject(class))
|
||||
return; /* XXX no error */
|
||||
ap = (accessobject *)op;
|
||||
XDECREF(ap->ac_class);
|
||||
XINCREF(class);
|
||||
ap->ac_class = class;
|
||||
}
|
||||
|
||||
object *
|
||||
getaccessvalue(op, class)
|
||||
object *op;
|
||||
object *class;
|
||||
{
|
||||
register accessobject *ap;
|
||||
if (!is_accessobject(op)) {
|
||||
err_badcall();
|
||||
return NULL;
|
||||
}
|
||||
ap = (accessobject *)op;
|
||||
|
||||
if (!classcheck(class, ap->ac_class, 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, class, value)
|
||||
object *op;
|
||||
object *class;
|
||||
object *value;
|
||||
{
|
||||
register accessobject *ap;
|
||||
if (!is_accessobject(op)) {
|
||||
err_badcall();
|
||||
return -1;
|
||||
}
|
||||
ap = (accessobject *)op;
|
||||
|
||||
if (!classcheck(class, ap->ac_class, 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
|
||||
classcheck(caller, owner, access, mode)
|
||||
object *caller;
|
||||
object *owner;
|
||||
int access;
|
||||
int mode;
|
||||
{
|
||||
if (caller == owner && owner != NULL)
|
||||
return access & mode & (AC_PRIVATE|AC_PROTECTED|AC_PUBLIC);
|
||||
if (caller != NULL && owner != NULL && issubclass(caller, owner))
|
||||
return access & mode & (AC_PROTECTED|AC_PUBLIC);
|
||||
return access & mode & AC_PUBLIC;
|
||||
}
|
||||
|
||||
/* Access methods */
|
||||
|
||||
static void
|
||||
access_dealloc(ap)
|
||||
accessobject *ap;
|
||||
{
|
||||
XDECREF(ap->ac_value);
|
||||
XDECREF(ap->ac_class);
|
||||
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_class", T_OBJECT, OFF(ac_class)},
|
||||
{"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];
|
||||
classobject *class = (classobject *)ap->ac_class;
|
||||
typeobject *type = ap->ac_type;
|
||||
sprintf(buf, "<access object, class %.100s, type %.100s, mode 0%o>",
|
||||
class ? getstringvalue(class->cl_name) : "-",
|
||||
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*/
|
||||
};
|
||||
|
||||
/* Dummy type objects to indicate classes 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*/
|
||||
};
|
|
@ -29,19 +29,14 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
#include "structmember.h"
|
||||
#include "ceval.h"
|
||||
|
||||
typedef struct {
|
||||
OB_HEAD
|
||||
object *cl_bases; /* A tuple */
|
||||
object *cl_methods; /* A dictionary */
|
||||
object *cl_name; /* A string */
|
||||
} classobject;
|
||||
|
||||
object *
|
||||
newclassobject(bases, methods, name)
|
||||
newclassobject(bases, dict, name)
|
||||
object *bases; /* NULL or tuple of classobjects! */
|
||||
object *methods;
|
||||
object *dict;
|
||||
object *name; /* String; NULL if unknown */
|
||||
{
|
||||
int pos;
|
||||
object *key, *value;
|
||||
classobject *op;
|
||||
if (bases == NULL) {
|
||||
bases = newtupleobject(0);
|
||||
|
@ -56,10 +51,15 @@ newclassobject(bases, methods, name)
|
|||
return NULL;
|
||||
}
|
||||
op->cl_bases = bases;
|
||||
INCREF(methods);
|
||||
op->cl_methods = methods;
|
||||
INCREF(dict);
|
||||
op->cl_dict = dict;
|
||||
XINCREF(name);
|
||||
op->cl_name = name;
|
||||
pos = 0;
|
||||
while (mappinggetnext(dict, &pos, &key, &value)) {
|
||||
if (is_accessobject(value))
|
||||
setaccessowner(value, (object *)op);
|
||||
}
|
||||
return (object *) op;
|
||||
}
|
||||
|
||||
|
@ -70,20 +70,43 @@ class_dealloc(op)
|
|||
classobject *op;
|
||||
{
|
||||
DECREF(op->cl_bases);
|
||||
DECREF(op->cl_methods);
|
||||
DECREF(op->cl_dict);
|
||||
XDECREF(op->cl_name);
|
||||
free((ANY *)op);
|
||||
}
|
||||
|
||||
static object *
|
||||
class_lookup(cp, name, pclass)
|
||||
classobject *cp;
|
||||
char *name;
|
||||
classobject **pclass;
|
||||
{
|
||||
int i, n;
|
||||
object *value = dictlookup(cp->cl_dict, name);
|
||||
if (value != NULL) {
|
||||
*pclass = cp;
|
||||
return value;
|
||||
}
|
||||
n = gettuplesize(cp->cl_bases);
|
||||
for (i = 0; i < n; i++) {
|
||||
object *v = class_lookup((classobject *)
|
||||
gettupleitem(cp->cl_bases, i), name, pclass);
|
||||
if (v != NULL)
|
||||
return v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static object *
|
||||
class_getattr(op, name)
|
||||
register classobject *op;
|
||||
register char *name;
|
||||
{
|
||||
register object *v;
|
||||
object *class;
|
||||
if (strcmp(name, "__dict__") == 0) {
|
||||
INCREF(op->cl_methods);
|
||||
return op->cl_methods;
|
||||
INCREF(op->cl_dict);
|
||||
return op->cl_dict;
|
||||
}
|
||||
if (strcmp(name, "__bases__") == 0) {
|
||||
INCREF(op->cl_bases);
|
||||
|
@ -97,25 +120,17 @@ class_getattr(op, name)
|
|||
INCREF(v);
|
||||
return v;
|
||||
}
|
||||
v = dictlookup(op->cl_methods, name);
|
||||
v = class_lookup(op, name, &class);
|
||||
if (v != NULL) {
|
||||
if (is_accessobject(v))
|
||||
v = getaccessvalue(v, (object *)NULL);
|
||||
v = getaccessvalue(v, getclass());
|
||||
else if (is_funcobject(v))
|
||||
v = newinstancemethodobject(v, (object *)NULL,
|
||||
(object *)class);
|
||||
else
|
||||
INCREF(v);
|
||||
return v;
|
||||
}
|
||||
{
|
||||
int n = gettuplesize(op->cl_bases);
|
||||
int i;
|
||||
for (i = 0; i < n; i++) {
|
||||
v = class_getattr((classobject *)
|
||||
gettupleitem(op->cl_bases, i), name);
|
||||
if (v != NULL)
|
||||
return v;
|
||||
err_clear();
|
||||
}
|
||||
}
|
||||
err_setstr(AttributeError, name);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -134,18 +149,18 @@ class_setattr(op, name, v)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
ac = dictlookup(op->cl_methods, name);
|
||||
ac = dictlookup(op->cl_dict, name);
|
||||
if (ac != NULL && is_accessobject(ac))
|
||||
return setaccessvalue(ac, (object *)NULL, v);
|
||||
return setaccessvalue(ac, getclass(), v);
|
||||
if (v == NULL) {
|
||||
int rv = dictremove(op->cl_methods, name);
|
||||
int rv = dictremove(op->cl_dict, name);
|
||||
if (rv < 0)
|
||||
err_setstr(AttributeError,
|
||||
"delete non-existing class attribute");
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
return dictinsert(op->cl_methods, name, v);
|
||||
return dictinsert(op->cl_dict, name, v);
|
||||
}
|
||||
|
||||
static object *
|
||||
|
@ -179,17 +194,71 @@ typeobject Classtype = {
|
|||
0, /*tp_as_mapping*/
|
||||
};
|
||||
|
||||
int
|
||||
issubclass(class, base)
|
||||
object *class;
|
||||
object *base;
|
||||
{
|
||||
int i, n;
|
||||
classobject *cp;
|
||||
if (class == NULL || !is_classobject(class))
|
||||
return 0;
|
||||
if (class == base)
|
||||
return 1;
|
||||
cp = (classobject *)class;
|
||||
n = gettuplesize(cp->cl_bases);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (issubclass(gettupleitem(cp->cl_bases, i), base))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We're not done yet: next, we define instance objects... */
|
||||
|
||||
/* Instance objects */
|
||||
|
||||
typedef struct {
|
||||
OB_HEAD
|
||||
classobject *in_class; /* The class object */
|
||||
object *in_attr; /* A dictionary */
|
||||
object *in_dict; /* A dictionary */
|
||||
} instanceobject;
|
||||
|
||||
static object *instance_getattr PROTO((instanceobject *, char *));
|
||||
|
||||
static int
|
||||
addaccess(class, inst)
|
||||
classobject *class;
|
||||
instanceobject *inst;
|
||||
{
|
||||
int i, n, pos, ret;
|
||||
object *key, *value, *ac;
|
||||
|
||||
n = gettuplesize(class->cl_bases);
|
||||
for (i = 0; i < n; i++) {
|
||||
if (addaccess(gettupleitem(class->cl_bases, i), inst) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
while (mappinggetnext(class->cl_dict, &pos, &key, &value)) {
|
||||
if (!is_accessobject(value))
|
||||
continue;
|
||||
ac = dict2lookup(inst->in_dict, key);
|
||||
if (ac != NULL && is_accessobject(ac)) {
|
||||
err_setval(ConflictError, key);
|
||||
return -1;
|
||||
}
|
||||
ac = cloneaccessobject(value);
|
||||
if (ac == NULL)
|
||||
return -1;
|
||||
ret = dict2insert(inst->in_dict, key, ac);
|
||||
DECREF(ac);
|
||||
if (ret != 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
object *
|
||||
newinstanceobject(class, arg)
|
||||
object *class;
|
||||
|
@ -198,8 +267,6 @@ newinstanceobject(class, arg)
|
|||
register instanceobject *inst;
|
||||
object *v;
|
||||
object *init;
|
||||
int pos;
|
||||
object *key, *value;
|
||||
if (!is_classobject(class)) {
|
||||
err_badcall();
|
||||
return NULL;
|
||||
|
@ -209,26 +276,12 @@ newinstanceobject(class, arg)
|
|||
return NULL;
|
||||
INCREF(class);
|
||||
inst->in_class = (classobject *)class;
|
||||
inst->in_attr = newdictobject();
|
||||
if (inst->in_attr == NULL) {
|
||||
error:
|
||||
inst->in_dict = newdictobject();
|
||||
if (inst->in_dict == NULL ||
|
||||
addaccess((classobject *)class, inst) != 0) {
|
||||
DECREF(inst);
|
||||
return NULL;
|
||||
}
|
||||
pos = 0;
|
||||
while (mappinggetnext(((classobject *)class)->cl_methods,
|
||||
&pos, &key, &value)) {
|
||||
if (is_accessobject(value)) {
|
||||
object *ac = cloneaccessobject(value);
|
||||
int err;
|
||||
if (ac == NULL)
|
||||
goto error;
|
||||
err = dict2insert(inst->in_attr, key, ac);
|
||||
DECREF(ac);
|
||||
if (err)
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
init = instance_getattr(inst, "__init__");
|
||||
if (init == NULL) {
|
||||
err_clear();
|
||||
|
@ -288,7 +341,7 @@ instance_dealloc(inst)
|
|||
if (--inst->ob_refcnt > 0)
|
||||
return; /* __del__ added a reference; don't delete now */
|
||||
DECREF(inst->in_class);
|
||||
XDECREF(inst->in_attr);
|
||||
XDECREF(inst->in_dict);
|
||||
free((ANY *)inst);
|
||||
}
|
||||
|
||||
|
@ -298,31 +351,30 @@ instance_getattr(inst, name)
|
|||
register char *name;
|
||||
{
|
||||
register object *v;
|
||||
classobject *class;
|
||||
if (strcmp(name, "__dict__") == 0) {
|
||||
INCREF(inst->in_attr);
|
||||
return inst->in_attr;
|
||||
INCREF(inst->in_dict);
|
||||
return inst->in_dict;
|
||||
}
|
||||
if (strcmp(name, "__class__") == 0) {
|
||||
INCREF(inst->in_class);
|
||||
return (object *)inst->in_class;
|
||||
}
|
||||
v = dictlookup(inst->in_attr, name);
|
||||
v = dictlookup(inst->in_dict, name);
|
||||
if (v != NULL) {
|
||||
if (is_accessobject(v))
|
||||
v = getaccessvalue(v, (object *)NULL);
|
||||
v = getaccessvalue(v, getclass());
|
||||
else
|
||||
INCREF(v);
|
||||
return v;
|
||||
}
|
||||
v = class_getattr(inst->in_class, name);
|
||||
v = class_lookup(inst->in_class, name, &class);
|
||||
if (v == NULL)
|
||||
return v; /* class_getattr() has set the error */
|
||||
if (is_funcobject(v)) {
|
||||
object *w = newinstancemethodobject(v, (object *)inst);
|
||||
DECREF(v);
|
||||
return w;
|
||||
}
|
||||
DECREF(v);
|
||||
goto error;
|
||||
if (is_funcobject(v))
|
||||
return newinstancemethodobject(v, (object *)inst,
|
||||
(object *)class);
|
||||
error:
|
||||
err_setstr(AttributeError, name);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -341,18 +393,18 @@ instance_setattr(inst, name, v)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
ac = dictlookup(inst->in_attr, name);
|
||||
ac = dictlookup(inst->in_dict, name);
|
||||
if (ac != NULL && is_accessobject(ac))
|
||||
return setaccessvalue(ac, (object *)NULL, v);
|
||||
return setaccessvalue(ac, getclass(), v);
|
||||
if (v == NULL) {
|
||||
int rv = dictremove(inst->in_attr, name);
|
||||
int rv = dictremove(inst->in_dict, name);
|
||||
if (rv < 0)
|
||||
err_setstr(AttributeError,
|
||||
"delete non-existing instance attribute");
|
||||
return rv;
|
||||
}
|
||||
else
|
||||
return dictinsert(inst->in_attr, name, v);
|
||||
return dictinsert(inst->in_dict, name, v);
|
||||
}
|
||||
|
||||
static object *
|
||||
|
@ -893,18 +945,24 @@ instance_convert(inst, methodname)
|
|||
}
|
||||
|
||||
|
||||
/* And finally, here are instance method objects */
|
||||
/* Instance method objects are used for two purposes:
|
||||
(a) as bound instance methods (returned by instancename.methodname)
|
||||
(b) as unbound methods (returned by ClassName.methodname)
|
||||
In case (b), im_self is NULL
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
OB_HEAD
|
||||
object *im_func; /* The method function */
|
||||
object *im_self; /* The object to which this applies */
|
||||
object *im_func; /* The function implementing the method */
|
||||
object *im_self; /* The instance it is bound to, or NULL */
|
||||
object *im_class; /* The class that defined the method */
|
||||
} instancemethodobject;
|
||||
|
||||
object *
|
||||
newinstancemethodobject(func, self)
|
||||
newinstancemethodobject(func, self, class)
|
||||
object *func;
|
||||
object *self;
|
||||
object *class;
|
||||
{
|
||||
register instancemethodobject *im;
|
||||
if (!is_funcobject(func)) {
|
||||
|
@ -916,8 +974,10 @@ newinstancemethodobject(func, self)
|
|||
return NULL;
|
||||
INCREF(func);
|
||||
im->im_func = func;
|
||||
INCREF(self);
|
||||
XINCREF(self);
|
||||
im->im_self = self;
|
||||
INCREF(class);
|
||||
im->im_class = class;
|
||||
return (object *)im;
|
||||
}
|
||||
|
||||
|
@ -943,6 +1003,17 @@ instancemethodgetself(im)
|
|||
return ((instancemethodobject *)im)->im_self;
|
||||
}
|
||||
|
||||
object *
|
||||
instancemethodgetclass(im)
|
||||
register object *im;
|
||||
{
|
||||
if (!is_instancemethodobject(im)) {
|
||||
err_badcall();
|
||||
return NULL;
|
||||
}
|
||||
return ((instancemethodobject *)im)->im_class;
|
||||
}
|
||||
|
||||
/* Class method methods */
|
||||
|
||||
#define OFF(x) offsetof(instancemethodobject, x)
|
||||
|
@ -950,6 +1021,7 @@ instancemethodgetself(im)
|
|||
static struct memberlist instancemethod_memberlist[] = {
|
||||
{"im_func", T_OBJECT, OFF(im_func)},
|
||||
{"im_self", T_OBJECT, OFF(im_self)},
|
||||
{"im_class", T_OBJECT, OFF(im_class)},
|
||||
{NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
|
@ -966,7 +1038,8 @@ instancemethod_dealloc(im)
|
|||
register instancemethodobject *im;
|
||||
{
|
||||
DECREF(im->im_func);
|
||||
DECREF(im->im_self);
|
||||
XDECREF(im->im_self);
|
||||
DECREF(im->im_class);
|
||||
free((ANY *)im);
|
||||
}
|
||||
|
||||
|
@ -985,20 +1058,32 @@ instancemethod_repr(a)
|
|||
instancemethodobject *a;
|
||||
{
|
||||
char buf[240];
|
||||
object *classname =
|
||||
((instanceobject *)(a->im_self))->in_class->cl_name;
|
||||
object *funcname = ((funcobject *)(a->im_func))->func_name;
|
||||
char *cname, *fname;
|
||||
if (classname != NULL && is_stringobject(classname))
|
||||
cname = getstringvalue(classname);
|
||||
instanceobject *self = (instanceobject *)(a->im_self);
|
||||
funcobject *func = (funcobject *)(a->im_func);
|
||||
classobject *class = (classobject *)(a->im_class);
|
||||
object *fclassname, *iclassname, *funcname;
|
||||
char *fcname, *icname, *fname;
|
||||
fclassname = class->cl_name;
|
||||
funcname = func->func_name;
|
||||
if (fclassname != NULL && is_stringobject(fclassname))
|
||||
fcname = getstringvalue(fclassname);
|
||||
else
|
||||
cname = "?";
|
||||
fcname = "?";
|
||||
if (funcname != NULL && is_stringobject(funcname))
|
||||
fname = getstringvalue(funcname);
|
||||
else
|
||||
fname = "?";
|
||||
sprintf(buf, "<method %.100s of %.100s instance at %lx>",
|
||||
fname, cname, (long)a->im_func);
|
||||
if (self == NULL)
|
||||
sprintf(buf, "<unbound method %.100s.%.100s>", fcname, fname);
|
||||
else {
|
||||
iclassname = self->in_class->cl_name;
|
||||
if (iclassname != NULL && is_stringobject(iclassname))
|
||||
icname = getstringvalue(iclassname);
|
||||
else
|
||||
icname = "?";
|
||||
sprintf(buf, "<method %.60s.%.60s of %.60s instance at %lx>",
|
||||
fcname, fname, icname, (long)self);
|
||||
}
|
||||
return newstringobject(buf);
|
||||
}
|
||||
|
||||
|
@ -1007,7 +1092,10 @@ instancemethod_hash(a)
|
|||
instancemethodobject *a;
|
||||
{
|
||||
long x, y;
|
||||
x = hashobject(a->im_self);
|
||||
if (a->im_self == NULL)
|
||||
x = hashobject(None);
|
||||
else
|
||||
x = hashobject(a->im_self);
|
||||
if (x == -1)
|
||||
return -1;
|
||||
y = hashobject(a->im_func);
|
||||
|
|
|
@ -38,6 +38,7 @@ static struct memberlist frame_memberlist[] = {
|
|||
{"f_code", T_OBJECT, OFF(f_code)},
|
||||
{"f_globals", T_OBJECT, OFF(f_globals)},
|
||||
{"f_locals", T_OBJECT, OFF(f_locals)},
|
||||
{"f_class", T_OBJECT, OFF(f_class)},
|
||||
/* {"f_fastlocals",T_OBJECT, OFF(f_fastlocals)}, /* XXX Unsafe */
|
||||
{"f_localmap", T_OBJECT, OFF(f_localmap)},
|
||||
{"f_lasti", T_INT, OFF(f_lasti)},
|
||||
|
@ -84,6 +85,7 @@ frame_dealloc(f)
|
|||
XDECREF(f->f_code);
|
||||
XDECREF(f->f_globals);
|
||||
XDECREF(f->f_locals);
|
||||
XDECREF(f->f_class);
|
||||
XDECREF(f->f_fastlocals);
|
||||
XDECREF(f->f_localmap);
|
||||
f->f_back = free_list;
|
||||
|
@ -108,11 +110,12 @@ typeobject Frametype = {
|
|||
};
|
||||
|
||||
frameobject *
|
||||
newframeobject(back, code, globals, locals, nvalues, nblocks)
|
||||
newframeobject(back, code, globals, locals, class, nvalues, nblocks)
|
||||
frameobject *back;
|
||||
codeobject *code;
|
||||
object *globals;
|
||||
object *locals;
|
||||
object *class;
|
||||
int nvalues;
|
||||
int nblocks;
|
||||
{
|
||||
|
@ -121,6 +124,7 @@ newframeobject(back, code, globals, locals, nvalues, nblocks)
|
|||
code == NULL || !is_codeobject(code) ||
|
||||
globals == NULL || !is_dictobject(globals) ||
|
||||
locals == NULL || !is_dictobject(locals) ||
|
||||
(class != NULL && !is_classobject(class)) ||
|
||||
nvalues < 0 || nblocks < 0) {
|
||||
err_badcall();
|
||||
return NULL;
|
||||
|
@ -146,6 +150,8 @@ newframeobject(back, code, globals, locals, nvalues, nblocks)
|
|||
f->f_globals = globals;
|
||||
INCREF(locals);
|
||||
f->f_locals = locals;
|
||||
XINCREF(class);
|
||||
f->f_class = class;
|
||||
f->f_fastlocals = NULL;
|
||||
f->f_localmap = NULL;
|
||||
if (nvalues > f->f_nvalues || f->f_valuestack == NULL) {
|
||||
|
|
|
@ -25,6 +25,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
/* Module object implementation */
|
||||
|
||||
#include "allobjects.h"
|
||||
#include "ceval.h"
|
||||
|
||||
typedef struct {
|
||||
OB_HEAD
|
||||
|
@ -111,7 +112,7 @@ module_getattr(m, name)
|
|||
err_setstr(AttributeError, name);
|
||||
else {
|
||||
if (is_accessobject(res))
|
||||
res = getaccessvalue(res, (object *)NULL);
|
||||
res = getaccessvalue(res, getclass());
|
||||
else
|
||||
INCREF(res);
|
||||
}
|
||||
|
@ -134,7 +135,7 @@ module_setattr(m, name, v)
|
|||
}
|
||||
ac = dictlookup(m->md_dict, name);
|
||||
if (ac != NULL && is_accessobject(ac))
|
||||
return setaccessvalue(ac, (object *)NULL, v);
|
||||
return setaccessvalue(ac, getclass(), v);
|
||||
if (v == NULL) {
|
||||
int rv = dictremove(m->md_dict, name);
|
||||
if (rv < 0)
|
||||
|
|
|
@ -212,7 +212,7 @@ exec_eval(v, start)
|
|||
}
|
||||
if (is_codeobject(str))
|
||||
return eval_code((codeobject *) str, globals, locals,
|
||||
(object *)NULL);
|
||||
(object *)NULL, (object *)NULL);
|
||||
s = getstringvalue(str);
|
||||
if (strlen(s) != getstringsize(str)) {
|
||||
err_setstr(ValueError, "embedded '\\0' in string arg");
|
||||
|
|
127
Python/ceval.c
127
Python/ceval.c
|
@ -161,10 +161,11 @@ enum why_code {
|
|||
/* Interpreter main loop */
|
||||
|
||||
object *
|
||||
eval_code(co, globals, locals, arg)
|
||||
eval_code(co, globals, locals, class, arg)
|
||||
codeobject *co;
|
||||
object *globals;
|
||||
object *locals;
|
||||
object *class;
|
||||
object *arg;
|
||||
{
|
||||
register unsigned char *next_instr;
|
||||
|
@ -244,6 +245,7 @@ eval_code(co, globals, locals, arg)
|
|||
co, /*code*/
|
||||
globals, /*globals*/
|
||||
locals, /*locals*/
|
||||
class, /*class*/
|
||||
50, /*nvalues*/
|
||||
20); /*nblocks*/
|
||||
if (f == NULL)
|
||||
|
@ -759,7 +761,7 @@ eval_code(co, globals, locals, arg)
|
|||
v = POP();
|
||||
u = dict2lookup(f->f_locals, w);
|
||||
if (u != NULL && is_accessobject(u)) {
|
||||
err = setaccessvalue(u, (object *)NULL, v);
|
||||
err = setaccessvalue(u, class, v);
|
||||
DECREF(v);
|
||||
break;
|
||||
}
|
||||
|
@ -771,7 +773,7 @@ eval_code(co, globals, locals, arg)
|
|||
w = GETNAMEV(oparg);
|
||||
u = dict2lookup(f->f_locals, w);
|
||||
if (u != NULL && is_accessobject(u)) {
|
||||
err = setaccessvalue(u, (object *)NULL,
|
||||
err = setaccessvalue(u, class,
|
||||
(object *)NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -969,7 +971,7 @@ eval_code(co, globals, locals, arg)
|
|||
v = POP();
|
||||
u = dict2lookup(f->f_locals, w);
|
||||
if (u != NULL && is_accessobject(u)) {
|
||||
err = setaccessvalue(u, (object *)NULL, v);
|
||||
err = setaccessvalue(u, class, v);
|
||||
DECREF(v);
|
||||
break;
|
||||
}
|
||||
|
@ -981,7 +983,7 @@ eval_code(co, globals, locals, arg)
|
|||
w = GETNAMEV(oparg);
|
||||
u = dict2lookup(f->f_locals, w);
|
||||
if (u != NULL && is_accessobject(u)) {
|
||||
err = setaccessvalue(u, (object *)NULL,
|
||||
err = setaccessvalue(u, class,
|
||||
(object *)NULL);
|
||||
break;
|
||||
}
|
||||
|
@ -1012,11 +1014,12 @@ eval_code(co, globals, locals, arg)
|
|||
}
|
||||
}
|
||||
if (is_accessobject(x)) {
|
||||
x = getaccessvalue(x, (object *)NULL);
|
||||
x = getaccessvalue(x, class);
|
||||
if (x == NULL)
|
||||
break;
|
||||
}
|
||||
INCREF(x);
|
||||
else
|
||||
INCREF(x);
|
||||
PUSH(x);
|
||||
break;
|
||||
|
||||
|
@ -1033,11 +1036,12 @@ eval_code(co, globals, locals, arg)
|
|||
}
|
||||
}
|
||||
if (is_accessobject(x)) {
|
||||
x = getaccessvalue(x, (object *)NULL);
|
||||
x = getaccessvalue(x, class);
|
||||
if (x == NULL)
|
||||
break;
|
||||
}
|
||||
INCREF(x);
|
||||
else
|
||||
INCREF(x);
|
||||
PUSH(x);
|
||||
break;
|
||||
|
||||
|
@ -1049,11 +1053,12 @@ eval_code(co, globals, locals, arg)
|
|||
break;
|
||||
}
|
||||
if (is_accessobject(x)) {
|
||||
x = getaccessvalue(x, (object *)NULL);
|
||||
x = getaccessvalue(x, class);
|
||||
if (x == NULL)
|
||||
break;
|
||||
}
|
||||
INCREF(x);
|
||||
else
|
||||
INCREF(x);
|
||||
PUSH(x);
|
||||
break;
|
||||
|
||||
|
@ -1084,11 +1089,12 @@ eval_code(co, globals, locals, arg)
|
|||
break;
|
||||
}
|
||||
if (is_accessobject(x)) {
|
||||
x = getaccessvalue(x, (object *)NULL);
|
||||
x = getaccessvalue(x, class);
|
||||
if (x == NULL)
|
||||
break;
|
||||
}
|
||||
INCREF(x);
|
||||
else
|
||||
INCREF(x);
|
||||
PUSH(x);
|
||||
break;
|
||||
|
||||
|
@ -1096,7 +1102,7 @@ eval_code(co, globals, locals, arg)
|
|||
v = POP();
|
||||
w = GETLISTITEM(fastlocals, oparg);
|
||||
if (w != NULL && is_accessobject(w)) {
|
||||
err = setaccessvalue(w, (object *)NULL, v);
|
||||
err = setaccessvalue(w, class, v);
|
||||
DECREF(v);
|
||||
break;
|
||||
}
|
||||
|
@ -1112,8 +1118,7 @@ eval_code(co, globals, locals, arg)
|
|||
break;
|
||||
}
|
||||
if (w != NULL && is_accessobject(w)) {
|
||||
err = setaccessvalue(w, (object *)NULL,
|
||||
(object *)NULL);
|
||||
err = setaccessvalue(w, class, (object *)NULL);
|
||||
break;
|
||||
}
|
||||
DECREF(x);
|
||||
|
@ -1643,6 +1648,15 @@ getglobals()
|
|||
return current_frame->f_globals;
|
||||
}
|
||||
|
||||
object *
|
||||
getclass()
|
||||
{
|
||||
if (current_frame == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return current_frame->f_class;
|
||||
}
|
||||
|
||||
void
|
||||
printtraceback(f)
|
||||
object *f;
|
||||
|
@ -1974,37 +1988,41 @@ call_function(func, arg)
|
|||
{
|
||||
object *newarg = NULL;
|
||||
object *newlocals, *newglobals;
|
||||
object *class = NULL;
|
||||
object *co, *v;
|
||||
|
||||
if (is_instancemethodobject(func)) {
|
||||
int argcount;
|
||||
object *self = instancemethodgetself(func);
|
||||
class = instancemethodgetclass(func);
|
||||
func = instancemethodgetfunc(func);
|
||||
if (arg == NULL)
|
||||
argcount = 0;
|
||||
else if (is_tupleobject(arg))
|
||||
argcount = gettuplesize(arg);
|
||||
else
|
||||
argcount = 1;
|
||||
newarg = newtupleobject(argcount + 1);
|
||||
if (newarg == NULL)
|
||||
return NULL;
|
||||
INCREF(self);
|
||||
settupleitem(newarg, 0, self);
|
||||
if (arg != NULL && !is_tupleobject(arg)) {
|
||||
INCREF(arg);
|
||||
settupleitem(newarg, 1, arg);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
object *v;
|
||||
for (i = 0; i < argcount; i++) {
|
||||
v = gettupleitem(arg, i);
|
||||
XINCREF(v);
|
||||
settupleitem(newarg, i+1, v);
|
||||
if (self != NULL) {
|
||||
int argcount;
|
||||
if (arg == NULL)
|
||||
argcount = 0;
|
||||
else if (is_tupleobject(arg))
|
||||
argcount = gettuplesize(arg);
|
||||
else
|
||||
argcount = 1;
|
||||
newarg = newtupleobject(argcount + 1);
|
||||
if (newarg == NULL)
|
||||
return NULL;
|
||||
INCREF(self);
|
||||
settupleitem(newarg, 0, self);
|
||||
if (arg != NULL && !is_tupleobject(arg)) {
|
||||
INCREF(arg);
|
||||
settupleitem(newarg, 1, arg);
|
||||
}
|
||||
else {
|
||||
int i;
|
||||
object *v;
|
||||
for (i = 0; i < argcount; i++) {
|
||||
v = gettupleitem(arg, i);
|
||||
XINCREF(v);
|
||||
settupleitem(newarg, i+1, v);
|
||||
}
|
||||
}
|
||||
arg = newarg;
|
||||
}
|
||||
arg = newarg;
|
||||
}
|
||||
else {
|
||||
if (!is_funcobject(func)) {
|
||||
|
@ -2031,7 +2049,7 @@ call_function(func, arg)
|
|||
newglobals = getfuncglobals(func);
|
||||
INCREF(newglobals);
|
||||
|
||||
v = eval_code((codeobject *)co, newglobals, newlocals, arg);
|
||||
v = eval_code((codeobject *)co, newglobals, newlocals, class, arg);
|
||||
|
||||
DECREF(newlocals);
|
||||
DECREF(newglobals);
|
||||
|
@ -2367,10 +2385,10 @@ access_statement(name, mode, f)
|
|||
int mode;
|
||||
frameobject *f;
|
||||
{
|
||||
object *value;
|
||||
int i = -1;
|
||||
object *ac;
|
||||
int ret;
|
||||
object *value, *ac;
|
||||
typeobject *type;
|
||||
int fastind, ret;
|
||||
fastind = -1;
|
||||
if (f->f_localmap == NULL)
|
||||
value = dict2lookup(f->f_locals, name);
|
||||
else {
|
||||
|
@ -2378,12 +2396,13 @@ access_statement(name, mode, f)
|
|||
if (value == NULL || !is_intobject(value))
|
||||
value = NULL;
|
||||
else {
|
||||
i = getintvalue(value);
|
||||
if (0 <= i && i < getlistsize(f->f_fastlocals))
|
||||
value = getlistitem(f->f_fastlocals, i);
|
||||
fastind = getintvalue(value);
|
||||
if (0 <= fastind &&
|
||||
fastind < getlistsize(f->f_fastlocals))
|
||||
value = getlistitem(f->f_fastlocals, fastind);
|
||||
else {
|
||||
value = NULL;
|
||||
i = -1;
|
||||
fastind = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2392,11 +2411,15 @@ access_statement(name, mode, f)
|
|||
return -1;
|
||||
}
|
||||
err_clear();
|
||||
ac = newaccessobject(value, (object*)NULL, (typeobject*)NULL, mode);
|
||||
if (value != NULL && value != None)
|
||||
type = value->ob_type;
|
||||
else
|
||||
type = NULL;
|
||||
ac = newaccessobject(value, (object*)NULL, type, mode);
|
||||
if (ac == NULL)
|
||||
return -1;
|
||||
if (i >= 0)
|
||||
ret = setlistitem(f->f_fastlocals, i, ac);
|
||||
if (fastind >= 0)
|
||||
ret = setlistitem(f->f_fastlocals, fastind, ac);
|
||||
else {
|
||||
ret = dict2insert(f->f_locals, name, ac);
|
||||
DECREF(ac);
|
||||
|
|
|
@ -1429,8 +1429,8 @@ com_access_stmt(c, n)
|
|||
/* Calculate the mode mask */
|
||||
mode = 0;
|
||||
for (j = i; j < NCH(n); j += 2) {
|
||||
int r=0,w=0,p=0;
|
||||
for (k=0; k<NCH(CHILD(n,j)); k++) {
|
||||
int r = 0, w = 0, p = 0;
|
||||
for (k = 0; k < NCH(CHILD(n,j)); k++) {
|
||||
if (strequ(STR(CHILD(CHILD(n,j),k)), "public"))
|
||||
p = 0;
|
||||
else if (strequ(STR(CHILD(CHILD(n,j),k)), "protected"))
|
||||
|
@ -1446,7 +1446,7 @@ com_access_stmt(c, n)
|
|||
STR(CHILD(CHILD(n,j),k)));
|
||||
}
|
||||
if (r == 0 && w == 0)
|
||||
r =w = 1;
|
||||
r = w = 1;
|
||||
if (p == 0) {
|
||||
if (r == 1) mode |= AC_R_PUBLIC;
|
||||
if (w == 1) mode |= AC_W_PUBLIC;
|
||||
|
|
|
@ -303,7 +303,7 @@ get_module(m, name, m_ret)
|
|||
}
|
||||
}
|
||||
}
|
||||
v = eval_code(co, d, d, (object *)NULL);
|
||||
v = eval_code(co, d, d, (object *)NULL, (object *)NULL);
|
||||
DECREF(co);
|
||||
return v;
|
||||
}
|
||||
|
@ -422,7 +422,7 @@ init_frozen(name)
|
|||
return -1;
|
||||
if ((m = add_module(name)) == NULL ||
|
||||
(d = getmoduledict(m)) == NULL ||
|
||||
(v = eval_code(co, d, d, (object *)NULL)) == NULL) {
|
||||
(v = eval_code(co, d, d, (object*)NULL, (object*)NULL)) == NULL) {
|
||||
DECREF(co);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ eval_node(n, filename, globals, locals)
|
|||
freetree(n);
|
||||
if (co == NULL)
|
||||
return NULL;
|
||||
v = eval_code(co, globals, locals, (object *)NULL);
|
||||
v = eval_code(co, globals, locals, (object *)NULL, (object *)NULL);
|
||||
DECREF(co);
|
||||
return v;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue