blob: 19d54dc14102141a28bd5c7939e8acbe5926ca6e [file] [log] [blame]
Guido van Rossum81daa321993-05-20 14:24:46 +00001/***********************************************************
Guido van Rossum6610ad91995-01-04 19:07:38 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum81daa321993-05-20 14:24:46 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum0dfcf751996-08-12 22:00:53 +000025#ifdef SUPPORT_OBSOLETE_ACCESS /* This object type is no longer supported */
26
Guido van Rossum81daa321993-05-20 14:24:46 +000027/* Access object implementation */
28
Guido van Rossum234f9421993-06-17 12:35:49 +000029/* XXX TO DO LIST
Guido van Rossum234f9421993-06-17 12:35:49 +000030 - __init__ and __del__ (and all other similar methods)
Guido van Rossumb6775db1994-08-01 11:34:53 +000031 should be usable even when private, not ignored
Guido van Rossum234f9421993-06-17 12:35:49 +000032*/
33
Guido van Rossum81daa321993-05-20 14:24:46 +000034#include "allobjects.h"
Guido van Rossumed18fdc1993-07-11 19:55:34 +000035#include "ceval.h"
Guido van Rossum81daa321993-05-20 14:24:46 +000036#include "structmember.h"
37#include "modsupport.h" /* For getargs() etc. */
38
39typedef struct {
40 OB_HEAD
41 object *ac_value;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000042 object *ac_owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000043 typeobject *ac_type;
44 int ac_mode;
45} accessobject;
46
47/* Forward */
48static int typecheck PROTO((object *, typeobject *));
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000049static int ownercheck PROTO((object *, object *, int, int));
Guido van Rossum81daa321993-05-20 14:24:46 +000050
51object *
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000052newaccessobject(value, owner, type, mode)
Guido van Rossum81daa321993-05-20 14:24:46 +000053 object *value;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000054 object *owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000055 typeobject *type;
56 int mode;
57{
58 accessobject *ap;
Guido van Rossum81daa321993-05-20 14:24:46 +000059 if (!typecheck(value, type)) {
60 err_setstr(AccessError,
61 "access: initial value has inappropriate type");
62 return NULL;
63 }
64 ap = NEWOBJ(accessobject, &Accesstype);
65 if (ap == NULL)
66 return NULL;
67 XINCREF(value);
68 ap->ac_value = value;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000069 XINCREF(owner);
70 ap->ac_owner = owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000071 XINCREF(type);
72 ap->ac_type = (typeobject *)type;
73 ap->ac_mode = mode;
74 return (object *)ap;
75}
76
77object *
78cloneaccessobject(op)
79 object *op;
80{
81 register accessobject *ap;
82 if (!is_accessobject(op)) {
83 err_badcall();
84 return NULL;
85 }
86 ap = (accessobject *)op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000087 return newaccessobject(ap->ac_value, ap->ac_owner,
Guido van Rossum81daa321993-05-20 14:24:46 +000088 ap->ac_type, ap->ac_mode);
89}
90
91void
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000092setaccessowner(op, owner)
Guido van Rossum81daa321993-05-20 14:24:46 +000093 object *op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000094 object *owner;
Guido van Rossum81daa321993-05-20 14:24:46 +000095{
96 register accessobject *ap;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +000097 if (!is_accessobject(op))
Guido van Rossum81daa321993-05-20 14:24:46 +000098 return; /* XXX no error */
99 ap = (accessobject *)op;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000100 XDECREF(ap->ac_owner);
101 XINCREF(owner);
102 ap->ac_owner = owner;
Guido van Rossum81daa321993-05-20 14:24:46 +0000103}
104
Guido van Rossumb3f72581993-05-21 19:56:10 +0000105int
106hasaccessvalue(op)
107 object *op;
108{
109 if (!is_accessobject(op))
110 return 0;
111 return ((accessobject *)op)->ac_value != NULL;
112}
113
Guido van Rossum81daa321993-05-20 14:24:46 +0000114object *
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000115getaccessvalue(op, caller)
Guido van Rossum81daa321993-05-20 14:24:46 +0000116 object *op;
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000117 object *caller;
Guido van Rossum81daa321993-05-20 14:24:46 +0000118{
119 register accessobject *ap;
120 if (!is_accessobject(op)) {
121 err_badcall();
122 return NULL;
123 }
124 ap = (accessobject *)op;
125
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000126 if (!ownercheck(caller, ap->ac_owner, AC_R, ap->ac_mode)) {
Guido van Rossum81daa321993-05-20 14:24:46 +0000127 err_setstr(AccessError, "read access denied");
128 return NULL;
129 }
130
131 if (ap->ac_value == NULL) {
132 err_setstr(AccessError, "no current value");
133 return NULL;
134 }
135 INCREF(ap->ac_value);
136 return ap->ac_value;
137}
138
139int
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000140setaccessvalue(op, caller, value)
Guido van Rossum81daa321993-05-20 14:24:46 +0000141 object *op;
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000142 object *caller;
Guido van Rossum81daa321993-05-20 14:24:46 +0000143 object *value;
144{
145 register accessobject *ap;
146 if (!is_accessobject(op)) {
147 err_badcall();
148 return -1;
149 }
150 ap = (accessobject *)op;
151
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000152 if (!ownercheck(caller, ap->ac_owner, AC_W, ap->ac_mode)) {
Guido van Rossum81daa321993-05-20 14:24:46 +0000153 err_setstr(AccessError, "write access denied");
154 return -1;
155 }
156
157 if (!typecheck(value, ap->ac_type)) {
158 err_setstr(AccessError, "assign value of inappropriate type");
159 return -1;
160 }
161
162 if (value == NULL) { /* Delete it */
163 if (ap->ac_value == NULL) {
164 err_setstr(AccessError, "no current value");
165 return -1;
166 }
167 DECREF(ap->ac_value);
168 ap->ac_value = NULL;
169 return 0;
170 }
171 XDECREF(ap->ac_value);
172 INCREF(value);
173 ap->ac_value = value;
174 return 0;
175}
176
177static int
178typecheck(value, type)
179 object *value;
180 typeobject *type;
181{
182 object *x;
183 if (value == NULL || type == NULL)
184 return 1; /* No check */
185 if (value->ob_type == type)
186 return 1; /* Exact match */
187 if (type == &Anynumbertype) {
188 if (value->ob_type->tp_as_number == NULL)
189 return 0;
190 if (!is_instanceobject(value))
191 return 1;
192 /* For instances, make sure it really looks like a number */
193 x = getattr(value, "__sub__");
194 if (x == NULL) {
195 err_clear();
196 return 0;
197 }
198 DECREF(x);
199 return 1;
200 }
201 if (type == &Anysequencetype) {
202 if (value->ob_type->tp_as_sequence == NULL)
203 return 0;
204 if (!is_instanceobject(value))
205 return 1;
206 /* For instances, make sure it really looks like a sequence */
207 x = getattr(value, "__getslice__");
208 if (x == NULL) {
209 err_clear();
210 return 0;
211 }
212 DECREF(x);
213 return 1;
214 }
215 if (type == &Anymappingtype) {
216 if (value->ob_type->tp_as_mapping == NULL)
217 return 0;
218 if (!is_instanceobject(value))
219 return 1;
220 /* For instances, make sure it really looks like a mapping */
221 x = getattr(value, "__getitem__");
222 if (x == NULL) {
223 err_clear();
224 return 0;
225 }
226 DECREF(x);
227 return 1;
228 }
229 return 0;
230}
231
232static int
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000233isprivileged(caller)
234 object *caller;
235{
236 object *g;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000237 static char privileged[] = "__privileged__";
238 if (caller != NULL && hasattr(caller, privileged))
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000239 return 1;
240 g = getglobals();
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000241 if (g != NULL && dictlookup(g, privileged))
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000242 return 1;
243 return 0;
244}
245
246static int
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000247ownercheck(caller, owner, access, mode)
Guido van Rossum81daa321993-05-20 14:24:46 +0000248 object *caller;
249 object *owner;
250 int access;
251 int mode;
252{
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000253 int mask = AC_PUBLIC;
Guido van Rossumed18fdc1993-07-11 19:55:34 +0000254 if (caller == owner || isprivileged(caller))
255 mask |= AC_PRIVATE | AC_PROTECTED;
256 else if (caller != NULL && owner != NULL &&
257 is_classobject(owner) && is_classobject(caller) &&
258 (issubclass(caller, owner) ||
259 issubclass(owner, caller)))
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000260 mask |= AC_PROTECTED;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000261 return access & mode & mask;
Guido van Rossum81daa321993-05-20 14:24:46 +0000262}
263
264/* Access methods */
265
266static void
267access_dealloc(ap)
268 accessobject *ap;
269{
270 XDECREF(ap->ac_value);
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000271 XDECREF(ap->ac_owner);
Guido van Rossum81daa321993-05-20 14:24:46 +0000272 XDECREF(ap->ac_type);
273 DEL(ap);
274}
275
276#define OFF(x) offsetof(accessobject, x)
277
278static struct memberlist access_memberlist[] = {
279 {"ac_value", T_OBJECT, OFF(ac_value)},
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000280 {"ac_owner", T_OBJECT, OFF(ac_owner)},
Guido van Rossum81daa321993-05-20 14:24:46 +0000281 {"ac_type", T_OBJECT, OFF(ac_type)},
282 {"ac_mode", T_INT, OFF(ac_mode)},
283 {NULL} /* Sentinel */
284};
285
286static object *
287access_getattr(ap, name)
288 accessobject *ap;
289 char *name;
290{
291 return getmember((char *)ap, access_memberlist, name);
292}
293
294static object *
295access_repr(ap)
296 accessobject *ap;
297{
298 char buf[300];
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000299 char buf2[20];
300 char *ownername;
Guido van Rossum81daa321993-05-20 14:24:46 +0000301 typeobject *type = ap->ac_type;
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000302 if (is_classobject(ap->ac_owner)) {
303 ownername =
304 getstringvalue(((classobject *)ap->ac_owner)->cl_name);
305 }
306 else {
307 sprintf(buf2, "0x%lx", (long)ap->ac_owner);
308 ownername = buf2;
309 }
Guido van Rossumb3f72581993-05-21 19:56:10 +0000310 sprintf(buf,
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000311 "<access object, value 0x%lx, owner %.100s, type %.100s, mode %04o>",
Guido van Rossumb3f72581993-05-21 19:56:10 +0000312 (long)(ap->ac_value),
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000313 ownername,
Guido van Rossum81daa321993-05-20 14:24:46 +0000314 type ? type->tp_name : "-",
315 ap->ac_mode);
316 return newstringobject(buf);
317}
318
319typeobject Accesstype = {
320 OB_HEAD_INIT(&Typetype)
321 0, /*ob_size*/
322 "access", /*tp_name*/
323 sizeof(accessobject), /*tp_size*/
324 0, /*tp_itemsize*/
325 /* methods */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000326 (destructor)access_dealloc, /*tp_dealloc*/
Guido van Rossum81daa321993-05-20 14:24:46 +0000327 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000328 (getattrfunc)access_getattr, /*tp_getattr*/
Guido van Rossum81daa321993-05-20 14:24:46 +0000329 0, /*tp_setattr*/
330 0, /*tp_compare*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000331 (reprfunc)access_repr, /*tp_repr*/
Guido van Rossum81daa321993-05-20 14:24:46 +0000332 0, /*tp_as_number*/
333 0, /*tp_as_sequence*/
334 0, /*tp_as_mapping*/
335 0, /*tp_hash*/
336};
337
Guido van Rossumeb6b33a1993-05-25 09:38:27 +0000338
339/* Pseudo type objects to indicate collections of types */
Guido van Rossum81daa321993-05-20 14:24:46 +0000340
341/* XXX This should be replaced by a more general "subclassing"
342 XXX mechanism for type objects... */
343
344typeobject Anynumbertype = {
345 OB_HEAD_INIT(&Typetype)
346 0, /*ob_size*/
347 "*number*", /*tp_name*/
348};
349
350/* XXX Should really distinguish mutable and immutable sequences as well */
351
352typeobject Anysequencetype = {
353 OB_HEAD_INIT(&Typetype)
354 0, /*ob_size*/
355 "*sequence*", /*tp_name*/
356};
357
358typeobject Anymappingtype = {
359 OB_HEAD_INIT(&Typetype)
360 0, /*ob_size*/
361 "*mapping*", /*tp_name*/
362};
Guido van Rossum0dfcf751996-08-12 22:00:53 +0000363
364#endif /* SUPPORT_OBSOLETE_ACCESS */