cpython/Objects/object.c

267 lines
4.7 KiB
C
Raw Normal View History

1990-12-20 11:06:42 -04:00
/* Generic object operations; and implementation of None (NoObject) */
1990-10-14 09:07:46 -03:00
1990-12-20 11:06:42 -04:00
#include "allobjects.h"
1990-10-14 09:07:46 -03:00
1990-12-20 11:06:42 -04:00
#ifdef REF_DEBUG
long ref_total;
#endif
1990-10-14 09:07:46 -03:00
1990-12-20 11:06:42 -04:00
/* Object allocation routines used by NEWOBJ and NEWVAROBJ macros.
These are used by the individual routines for object creation.
Do not call them otherwise, they do not initialize the object! */
1990-10-14 09:07:46 -03:00
object *
newobject(tp)
typeobject *tp;
{
object *op = (object *) malloc(tp->tp_basicsize);
if (op == NULL)
return err_nomem();
NEWREF(op);
op->ob_type = tp;
return op;
}
#if 0 /* unused */
varobject *
newvarobject(tp, size)
typeobject *tp;
unsigned int size;
{
varobject *op = (varobject *)
malloc(tp->tp_basicsize + size * tp->tp_itemsize);
if (op == NULL)
return err_nomem();
NEWREF(op);
op->ob_type = tp;
op->ob_size = size;
return op;
}
#endif
1990-12-20 11:06:42 -04:00
int StopPrint; /* Flag to indicate printing must be stopped */
1990-10-14 09:07:46 -03:00
static int prlevel;
void
printobject(op, fp, flags)
object *op;
FILE *fp;
int flags;
{
/* Hacks to make printing a long or recursive object interruptible */
1990-12-20 11:06:42 -04:00
/* XXX Interrupts should leave a more permanent error */
1990-10-14 09:07:46 -03:00
prlevel++;
if (!StopPrint && intrcheck()) {
fprintf(fp, "\n[print interrupted]\n");
StopPrint = 1;
}
if (!StopPrint) {
if (op == NULL) {
fprintf(fp, "<nil>");
}
else {
1990-12-20 11:06:42 -04:00
if (op->ob_refcnt <= 0)
fprintf(fp, "(refcnt %d):", op->ob_refcnt);
if (op->ob_type->tp_print == NULL) {
fprintf(fp, "<%s object at %lx>",
op->ob_type->tp_name, (long)op);
}
else {
(*op->ob_type->tp_print)(op, fp, flags);
}
1990-10-14 09:07:46 -03:00
}
}
prlevel--;
if (prlevel == 0)
StopPrint = 0;
}
object *
reprobject(v)
object *v;
{
1990-12-20 11:06:42 -04:00
object *w = NULL;
1990-10-14 09:07:46 -03:00
/* Hacks to make converting a long or recursive object interruptible */
prlevel++;
if (!StopPrint && intrcheck()) {
StopPrint = 1;
err_set(KeyboardInterrupt);
}
if (!StopPrint) {
if (v == NULL) {
1990-12-20 11:06:42 -04:00
w = newstringobject("<NULL>");
1990-10-14 09:07:46 -03:00
}
else if (v->ob_type->tp_repr == NULL) {
char buf[100];
sprintf(buf, "<%.80s object at %lx>",
v->ob_type->tp_name, (long)v);
w = newstringobject(buf);
}
else {
w = (*v->ob_type->tp_repr)(v);
}
1990-12-20 11:06:42 -04:00
if (StopPrint) {
XDECREF(w);
w = NULL;
}
1990-10-14 09:07:46 -03:00
}
prlevel--;
if (prlevel == 0)
StopPrint = 0;
return w;
}
int
cmpobject(v, w)
object *v, *w;
{
typeobject *tp;
if (v == w)
return 0;
if (v == NULL)
return -1;
if (w == NULL)
return 1;
if ((tp = v->ob_type) != w->ob_type)
return strcmp(tp->tp_name, w->ob_type->tp_name);
if (tp->tp_compare == NULL)
return (v < w) ? -1 : 1;
return ((*tp->tp_compare)(v, w));
}
1990-12-20 11:06:42 -04:00
object *
getattr(v, name)
object *v;
char *name;
{
if (v->ob_type->tp_getattr == NULL) {
err_setstr(TypeError, "attribute-less object");
return NULL;
}
else {
return (*v->ob_type->tp_getattr)(v, name);
}
}
int
setattr(v, name, w)
object *v;
char *name;
object *w;
{
if (v->ob_type->tp_setattr == NULL) {
if (v->ob_type->tp_getattr == NULL)
err_setstr(TypeError, "attribute-less object");
else
err_setstr(TypeError, "object has read-only attributes");
1990-12-20 19:12:40 -04:00
return -1;
1990-12-20 11:06:42 -04:00
}
else {
return (*v->ob_type->tp_setattr)(v, name, w);
}
}
1990-10-14 09:07:46 -03:00
/*
NoObject is usable as a non-NULL undefined value, used by the macro None.
There is (and should be!) no way to create other objects of this type,
1990-12-20 11:06:42 -04:00
so there is exactly one (which is indestructible, by the way).
1990-10-14 09:07:46 -03:00
*/
static void
1990-12-20 11:06:42 -04:00
none_print(op, fp, flags)
1990-10-14 09:07:46 -03:00
object *op;
FILE *fp;
int flags;
{
1990-12-20 11:06:42 -04:00
fprintf(fp, "None");
}
static object *
none_repr(op)
object *op;
{
return newstringobject("None");
1990-10-14 09:07:46 -03:00
}
static typeobject Notype = {
OB_HEAD_INIT(&Typetype)
0,
1990-12-20 11:06:42 -04:00
"None",
1990-10-14 09:07:46 -03:00
0,
0,
0, /*tp_dealloc*/ /*never called*/
1990-12-20 11:06:42 -04:00
none_print, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
none_repr, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
1990-10-14 09:07:46 -03:00
};
object NoObject = {
OB_HEAD_INIT(&Notype)
};
#ifdef TRACE_REFS
static object refchain = {&refchain, &refchain};
NEWREF(op)
object *op;
{
ref_total++;
op->ob_refcnt = 1;
op->_ob_next = refchain._ob_next;
op->_ob_prev = &refchain;
refchain._ob_next->_ob_prev = op;
refchain._ob_next = op;
}
1990-12-20 11:06:42 -04:00
UNREF(op)
register object *op;
1990-10-14 09:07:46 -03:00
{
1990-12-20 11:06:42 -04:00
register object *p;
if (op->ob_refcnt < 0) {
1990-12-20 11:06:42 -04:00
fprintf(stderr, "UNREF negative refcnt\n");
abort();
}
for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
if (p == op)
break;
}
if (p == &refchain) { /* Not found */
fprintf(stderr, "UNREF unknown object\n");
abort();
}
1990-10-14 09:07:46 -03:00
op->_ob_next->_ob_prev = op->_ob_prev;
op->_ob_prev->_ob_next = op->_ob_next;
1990-12-20 11:06:42 -04:00
}
DELREF(op)
object *op;
{
UNREF(op);
1990-10-14 09:07:46 -03:00
(*(op)->ob_type->tp_dealloc)(op);
}
printrefs(fp)
FILE *fp;
{
object *op;
fprintf(fp, "Remaining objects:\n");
for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
fprintf(fp, "[%d] ", op->ob_refcnt);
printobject(op, fp, 0);
putc('\n', fp);
}
}
#endif