summaryrefslogtreecommitdiff
path: root/sys/src/cmd/python/Objects
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2021-06-14 00:00:37 +0000
committerOri Bernstein <ori@eigenstate.org>2021-06-14 00:00:37 +0000
commita73a964e51247ed169d322c725a3a18859f109a3 (patch)
tree3f752d117274d444bda44e85609aeac1acf313f3 /sys/src/cmd/python/Objects
parente64efe273fcb921a61bf27d33b230c4e64fcd425 (diff)
python, hg: tow outside the environment.
they've served us well, and can ride off into the sunset.
Diffstat (limited to 'sys/src/cmd/python/Objects')
-rw-r--r--sys/src/cmd/python/Objects/abstract.c2381
-rw-r--r--sys/src/cmd/python/Objects/boolobject.c201
-rw-r--r--sys/src/cmd/python/Objects/bufferobject.c706
-rw-r--r--sys/src/cmd/python/Objects/cellobject.c133
-rw-r--r--sys/src/cmd/python/Objects/classobject.c2580
-rw-r--r--sys/src/cmd/python/Objects/cobject.c161
-rw-r--r--sys/src/cmd/python/Objects/codeobject.c590
-rw-r--r--sys/src/cmd/python/Objects/complexobject.c1031
-rw-r--r--sys/src/cmd/python/Objects/descrobject.c1283
-rw-r--r--sys/src/cmd/python/Objects/dictnotes.txt250
-rw-r--r--sys/src/cmd/python/Objects/dictobject.c2486
-rw-r--r--sys/src/cmd/python/Objects/enumobject.c298
-rw-r--r--sys/src/cmd/python/Objects/exceptions.c2147
-rw-r--r--sys/src/cmd/python/Objects/fileobject.c2487
-rw-r--r--sys/src/cmd/python/Objects/floatobject.c1748
-rw-r--r--sys/src/cmd/python/Objects/frameobject.c849
-rw-r--r--sys/src/cmd/python/Objects/funcobject.c888
-rw-r--r--sys/src/cmd/python/Objects/genobject.c383
-rw-r--r--sys/src/cmd/python/Objects/intobject.c1280
-rw-r--r--sys/src/cmd/python/Objects/iterobject.c232
-rw-r--r--sys/src/cmd/python/Objects/listobject.c2930
-rw-r--r--sys/src/cmd/python/Objects/listsort.txt677
-rw-r--r--sys/src/cmd/python/Objects/longobject.c3458
-rw-r--r--sys/src/cmd/python/Objects/methodobject.c365
-rw-r--r--sys/src/cmd/python/Objects/mkfile46
-rw-r--r--sys/src/cmd/python/Objects/moduleobject.c259
-rw-r--r--sys/src/cmd/python/Objects/object.c2139
-rw-r--r--sys/src/cmd/python/Objects/obmalloc.c1745
-rw-r--r--sys/src/cmd/python/Objects/rangeobject.c301
-rw-r--r--sys/src/cmd/python/Objects/setobject.c2312
-rw-r--r--sys/src/cmd/python/Objects/sliceobject.c351
-rw-r--r--sys/src/cmd/python/Objects/stringlib/README.txt34
-rw-r--r--sys/src/cmd/python/Objects/stringlib/count.h37
-rw-r--r--sys/src/cmd/python/Objects/stringlib/fastsearch.h104
-rw-r--r--sys/src/cmd/python/Objects/stringlib/find.h113
-rw-r--r--sys/src/cmd/python/Objects/stringlib/partition.h111
-rw-r--r--sys/src/cmd/python/Objects/stringobject.c5009
-rw-r--r--sys/src/cmd/python/Objects/structseq.c407
-rw-r--r--sys/src/cmd/python/Objects/tupleobject.c890
-rw-r--r--sys/src/cmd/python/Objects/typeobject.c5891
-rw-r--r--sys/src/cmd/python/Objects/unicodectype.c789
-rw-r--r--sys/src/cmd/python/Objects/unicodeobject.c8067
-rw-r--r--sys/src/cmd/python/Objects/unicodetype_db.h1269
-rw-r--r--sys/src/cmd/python/Objects/weakrefobject.c941
44 files changed, 0 insertions, 60359 deletions
diff --git a/sys/src/cmd/python/Objects/abstract.c b/sys/src/cmd/python/Objects/abstract.c
deleted file mode 100644
index f7a3bfefb..000000000
--- a/sys/src/cmd/python/Objects/abstract.c
+++ /dev/null
@@ -1,2381 +0,0 @@
-/* Abstract Object Interface (many thanks to Jim Fulton) */
-
-#include "Python.h"
-#include <ctype.h>
-#include "structmember.h" /* we need the offsetof() macro from there */
-#include "longintrepr.h"
-
-#define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
- Py_TPFLAGS_CHECKTYPES)
-
-
-/* Shorthands to return certain errors */
-
-static PyObject *
-type_error(const char *msg, PyObject *obj)
-{
- PyErr_Format(PyExc_TypeError, msg, obj->ob_type->tp_name);
- return NULL;
-}
-
-static PyObject *
-null_error(void)
-{
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_SystemError,
- "null argument to internal routine");
- return NULL;
-}
-
-/* Operations on any object */
-
-int
-PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
-{
- int r;
-
- if (o1 == NULL || o2 == NULL) {
- null_error();
- return -1;
- }
- r = PyObject_Compare(o1, o2);
- if (PyErr_Occurred())
- return -1;
- *result = r;
- return 0;
-}
-
-PyObject *
-PyObject_Type(PyObject *o)
-{
- PyObject *v;
-
- if (o == NULL)
- return null_error();
- v = (PyObject *)o->ob_type;
- Py_INCREF(v);
- return v;
-}
-
-Py_ssize_t
-PyObject_Size(PyObject *o)
-{
- PySequenceMethods *m;
-
- if (o == NULL) {
- null_error();
- return -1;
- }
-
- m = o->ob_type->tp_as_sequence;
- if (m && m->sq_length)
- return m->sq_length(o);
-
- return PyMapping_Size(o);
-}
-
-#undef PyObject_Length
-Py_ssize_t
-PyObject_Length(PyObject *o)
-{
- return PyObject_Size(o);
-}
-#define PyObject_Length PyObject_Size
-
-Py_ssize_t
-_PyObject_LengthHint(PyObject *o)
-{
- Py_ssize_t rv = PyObject_Size(o);
- if (rv != -1)
- return rv;
- if (PyErr_ExceptionMatches(PyExc_TypeError) ||
- PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyObject *err_type, *err_value, *err_tb, *ro;
-
- PyErr_Fetch(&err_type, &err_value, &err_tb);
- ro = PyObject_CallMethod(o, "__length_hint__", NULL);
- if (ro != NULL) {
- rv = PyInt_AsLong(ro);
- Py_DECREF(ro);
- Py_XDECREF(err_type);
- Py_XDECREF(err_value);
- Py_XDECREF(err_tb);
- return rv;
- }
- PyErr_Restore(err_type, err_value, err_tb);
- }
- return -1;
-}
-
-PyObject *
-PyObject_GetItem(PyObject *o, PyObject *key)
-{
- PyMappingMethods *m;
-
- if (o == NULL || key == NULL)
- return null_error();
-
- m = o->ob_type->tp_as_mapping;
- if (m && m->mp_subscript)
- return m->mp_subscript(o, key);
-
- if (o->ob_type->tp_as_sequence) {
- if (PyIndex_Check(key)) {
- Py_ssize_t key_value;
- key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
- if (key_value == -1 && PyErr_Occurred())
- return NULL;
- return PySequence_GetItem(o, key_value);
- }
- else if (o->ob_type->tp_as_sequence->sq_item)
- return type_error("sequence index must "
- "be integer, not '%.200s'", key);
- }
-
- return type_error("'%.200s' object is unsubscriptable", o);
-}
-
-int
-PyObject_SetItem(PyObject *o, PyObject *key, PyObject *value)
-{
- PyMappingMethods *m;
-
- if (o == NULL || key == NULL || value == NULL) {
- null_error();
- return -1;
- }
- m = o->ob_type->tp_as_mapping;
- if (m && m->mp_ass_subscript)
- return m->mp_ass_subscript(o, key, value);
-
- if (o->ob_type->tp_as_sequence) {
- if (PyIndex_Check(key)) {
- Py_ssize_t key_value;
- key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
- if (key_value == -1 && PyErr_Occurred())
- return -1;
- return PySequence_SetItem(o, key_value, value);
- }
- else if (o->ob_type->tp_as_sequence->sq_ass_item) {
- type_error("sequence index must be "
- "integer, not '%.200s'", key);
- return -1;
- }
- }
-
- type_error("'%.200s' object does not support item assignment", o);
- return -1;
-}
-
-int
-PyObject_DelItem(PyObject *o, PyObject *key)
-{
- PyMappingMethods *m;
-
- if (o == NULL || key == NULL) {
- null_error();
- return -1;
- }
- m = o->ob_type->tp_as_mapping;
- if (m && m->mp_ass_subscript)
- return m->mp_ass_subscript(o, key, (PyObject*)NULL);
-
- if (o->ob_type->tp_as_sequence) {
- if (PyIndex_Check(key)) {
- Py_ssize_t key_value;
- key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);
- if (key_value == -1 && PyErr_Occurred())
- return -1;
- return PySequence_DelItem(o, key_value);
- }
- else if (o->ob_type->tp_as_sequence->sq_ass_item) {
- type_error("sequence index must be "
- "integer, not '%.200s'", key);
- return -1;
- }
- }
-
- type_error("'%.200s' object does not support item deletion", o);
- return -1;
-}
-
-int
-PyObject_DelItemString(PyObject *o, char *key)
-{
- PyObject *okey;
- int ret;
-
- if (o == NULL || key == NULL) {
- null_error();
- return -1;
- }
- okey = PyString_FromString(key);
- if (okey == NULL)
- return -1;
- ret = PyObject_DelItem(o, okey);
- Py_DECREF(okey);
- return ret;
-}
-
-int
-PyObject_AsCharBuffer(PyObject *obj,
- const char **buffer,
- Py_ssize_t *buffer_len)
-{
- PyBufferProcs *pb;
- char *pp;
- Py_ssize_t len;
-
- if (obj == NULL || buffer == NULL || buffer_len == NULL) {
- null_error();
- return -1;
- }
- pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL ||
- pb->bf_getcharbuffer == NULL ||
- pb->bf_getsegcount == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected a character buffer object");
- return -1;
- }
- if ((*pb->bf_getsegcount)(obj,NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
- return -1;
- }
- len = (*pb->bf_getcharbuffer)(obj, 0, &pp);
- if (len < 0)
- return -1;
- *buffer = pp;
- *buffer_len = len;
- return 0;
-}
-
-int
-PyObject_CheckReadBuffer(PyObject *obj)
-{
- PyBufferProcs *pb = obj->ob_type->tp_as_buffer;
-
- if (pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL ||
- (*pb->bf_getsegcount)(obj, NULL) != 1)
- return 0;
- return 1;
-}
-
-int PyObject_AsReadBuffer(PyObject *obj,
- const void **buffer,
- Py_ssize_t *buffer_len)
-{
- PyBufferProcs *pb;
- void *pp;
- Py_ssize_t len;
-
- if (obj == NULL || buffer == NULL || buffer_len == NULL) {
- null_error();
- return -1;
- }
- pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected a readable buffer object");
- return -1;
- }
- if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
- return -1;
- }
- len = (*pb->bf_getreadbuffer)(obj, 0, &pp);
- if (len < 0)
- return -1;
- *buffer = pp;
- *buffer_len = len;
- return 0;
-}
-
-int PyObject_AsWriteBuffer(PyObject *obj,
- void **buffer,
- Py_ssize_t *buffer_len)
-{
- PyBufferProcs *pb;
- void*pp;
- Py_ssize_t len;
-
- if (obj == NULL || buffer == NULL || buffer_len == NULL) {
- null_error();
- return -1;
- }
- pb = obj->ob_type->tp_as_buffer;
- if (pb == NULL ||
- pb->bf_getwritebuffer == NULL ||
- pb->bf_getsegcount == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "expected a writeable buffer object");
- return -1;
- }
- if ((*pb->bf_getsegcount)(obj, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "expected a single-segment buffer object");
- return -1;
- }
- len = (*pb->bf_getwritebuffer)(obj,0,&pp);
- if (len < 0)
- return -1;
- *buffer = pp;
- *buffer_len = len;
- return 0;
-}
-
-/* Operations on numbers */
-
-int
-PyNumber_Check(PyObject *o)
-{
- return o && o->ob_type->tp_as_number &&
- (o->ob_type->tp_as_number->nb_int ||
- o->ob_type->tp_as_number->nb_float);
-}
-
-/* Binary operators */
-
-/* New style number protocol support */
-
-#define NB_SLOT(x) offsetof(PyNumberMethods, x)
-#define NB_BINOP(nb_methods, slot) \
- (*(binaryfunc*)(& ((char*)nb_methods)[slot]))
-#define NB_TERNOP(nb_methods, slot) \
- (*(ternaryfunc*)(& ((char*)nb_methods)[slot]))
-
-/*
- Calling scheme used for binary operations:
-
- v w Action
- -------------------------------------------------------------------
- new new w.op(v,w)[*], v.op(v,w), w.op(v,w)
- new old v.op(v,w), coerce(v,w), v.op(v,w)
- old new w.op(v,w), coerce(v,w), v.op(v,w)
- old old coerce(v,w), v.op(v,w)
-
- [*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of
- v->ob_type
-
- Legend:
- -------
- * new == new style number
- * old == old style number
- * Action indicates the order in which operations are tried until either
- a valid result is produced or an error occurs.
-
- */
-
-static PyObject *
-binary_op1(PyObject *v, PyObject *w, const int op_slot)
-{
- PyObject *x;
- binaryfunc slotv = NULL;
- binaryfunc slotw = NULL;
-
- if (v->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(v))
- slotv = NB_BINOP(v->ob_type->tp_as_number, op_slot);
- if (w->ob_type != v->ob_type &&
- w->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(w)) {
- slotw = NB_BINOP(w->ob_type->tp_as_number, op_slot);
- if (slotw == slotv)
- slotw = NULL;
- }
- if (slotv) {
- if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {
- x = slotw(v, w);
- if (x != Py_NotImplemented)
- return x;
- Py_DECREF(x); /* can't do it */
- slotw = NULL;
- }
- x = slotv(v, w);
- if (x != Py_NotImplemented)
- return x;
- Py_DECREF(x); /* can't do it */
- }
- if (slotw) {
- x = slotw(v, w);
- if (x != Py_NotImplemented)
- return x;
- Py_DECREF(x); /* can't do it */
- }
- if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w)) {
- int err = PyNumber_CoerceEx(&v, &w);
- if (err < 0) {
- return NULL;
- }
- if (err == 0) {
- PyNumberMethods *mv = v->ob_type->tp_as_number;
- if (mv) {
- binaryfunc slot;
- slot = NB_BINOP(mv, op_slot);
- if (slot) {
- x = slot(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- return x;
- }
- }
- /* CoerceEx incremented the reference counts */
- Py_DECREF(v);
- Py_DECREF(w);
- }
- }
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-static PyObject *
-binop_type_error(PyObject *v, PyObject *w, const char *op_name)
-{
- PyErr_Format(PyExc_TypeError,
- "unsupported operand type(s) for %.100s: "
- "'%.100s' and '%.100s'",
- op_name,
- v->ob_type->tp_name,
- w->ob_type->tp_name);
- return NULL;
-}
-
-static PyObject *
-binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name)
-{
- PyObject *result = binary_op1(v, w, op_slot);
- if (result == Py_NotImplemented) {
- Py_DECREF(result);
- return binop_type_error(v, w, op_name);
- }
- return result;
-}
-
-
-/*
- Calling scheme used for ternary operations:
-
- *** In some cases, w.op is called before v.op; see binary_op1. ***
-
- v w z Action
- -------------------------------------------------------------------
- new new new v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
- new old new v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
- old new new w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
- old old new z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
- new new old v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
- new old old v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
- old new old w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
- old old old coerce(v,w,z), v.op(v,w,z)
-
- Legend:
- -------
- * new == new style number
- * old == old style number
- * Action indicates the order in which operations are tried until either
- a valid result is produced or an error occurs.
- * coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
- only if z != Py_None; if z == Py_None, then it is treated as absent
- variable and only coerce(v,w) is tried.
-
- */
-
-static PyObject *
-ternary_op(PyObject *v,
- PyObject *w,
- PyObject *z,
- const int op_slot,
- const char *op_name)
-{
- PyNumberMethods *mv, *mw, *mz;
- PyObject *x = NULL;
- ternaryfunc slotv = NULL;
- ternaryfunc slotw = NULL;
- ternaryfunc slotz = NULL;
-
- mv = v->ob_type->tp_as_number;
- mw = w->ob_type->tp_as_number;
- if (mv != NULL && NEW_STYLE_NUMBER(v))
- slotv = NB_TERNOP(mv, op_slot);
- if (w->ob_type != v->ob_type &&
- mw != NULL && NEW_STYLE_NUMBER(w)) {
- slotw = NB_TERNOP(mw, op_slot);
- if (slotw == slotv)
- slotw = NULL;
- }
- if (slotv) {
- if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {
- x = slotw(v, w, z);
- if (x != Py_NotImplemented)
- return x;
- Py_DECREF(x); /* can't do it */
- slotw = NULL;
- }
- x = slotv(v, w, z);
- if (x != Py_NotImplemented)
- return x;
- Py_DECREF(x); /* can't do it */
- }
- if (slotw) {
- x = slotw(v, w, z);
- if (x != Py_NotImplemented)
- return x;
- Py_DECREF(x); /* can't do it */
- }
- mz = z->ob_type->tp_as_number;
- if (mz != NULL && NEW_STYLE_NUMBER(z)) {
- slotz = NB_TERNOP(mz, op_slot);
- if (slotz == slotv || slotz == slotw)
- slotz = NULL;
- if (slotz) {
- x = slotz(v, w, z);
- if (x != Py_NotImplemented)
- return x;
- Py_DECREF(x); /* can't do it */
- }
- }
-
- if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w) ||
- (z != Py_None && !NEW_STYLE_NUMBER(z))) {
- /* we have an old style operand, coerce */
- PyObject *v1, *z1, *w2, *z2;
- int c;
-
- c = PyNumber_Coerce(&v, &w);
- if (c != 0)
- goto error3;
-
- /* Special case: if the third argument is None, it is
- treated as absent argument and not coerced. */
- if (z == Py_None) {
- if (v->ob_type->tp_as_number) {
- slotz = NB_TERNOP(v->ob_type->tp_as_number,
- op_slot);
- if (slotz)
- x = slotz(v, w, z);
- else
- c = -1;
- }
- else
- c = -1;
- goto error2;
- }
- v1 = v;
- z1 = z;
- c = PyNumber_Coerce(&v1, &z1);
- if (c != 0)
- goto error2;
- w2 = w;
- z2 = z1;
- c = PyNumber_Coerce(&w2, &z2);
- if (c != 0)
- goto error1;
-
- if (v1->ob_type->tp_as_number != NULL) {
- slotv = NB_TERNOP(v1->ob_type->tp_as_number,
- op_slot);
- if (slotv)
- x = slotv(v1, w2, z2);
- else
- c = -1;
- }
- else
- c = -1;
-
- Py_DECREF(w2);
- Py_DECREF(z2);
- error1:
- Py_DECREF(v1);
- Py_DECREF(z1);
- error2:
- Py_DECREF(v);
- Py_DECREF(w);
- error3:
- if (c >= 0)
- return x;
- }
-
- if (z == Py_None)
- PyErr_Format(
- PyExc_TypeError,
- "unsupported operand type(s) for ** or pow(): "
- "'%.100s' and '%.100s'",
- v->ob_type->tp_name,
- w->ob_type->tp_name);
- else
- PyErr_Format(
- PyExc_TypeError,
- "unsupported operand type(s) for pow(): "
- "'%.100s', '%.100s', '%.100s'",
- v->ob_type->tp_name,
- w->ob_type->tp_name,
- z->ob_type->tp_name);
- return NULL;
-}
-
-#define BINARY_FUNC(func, op, op_name) \
- PyObject * \
- func(PyObject *v, PyObject *w) { \
- return binary_op(v, w, NB_SLOT(op), op_name); \
- }
-
-BINARY_FUNC(PyNumber_Or, nb_or, "|")
-BINARY_FUNC(PyNumber_Xor, nb_xor, "^")
-BINARY_FUNC(PyNumber_And, nb_and, "&")
-BINARY_FUNC(PyNumber_Lshift, nb_lshift, "<<")
-BINARY_FUNC(PyNumber_Rshift, nb_rshift, ">>")
-BINARY_FUNC(PyNumber_Subtract, nb_subtract, "-")
-BINARY_FUNC(PyNumber_Divide, nb_divide, "/")
-BINARY_FUNC(PyNumber_Divmod, nb_divmod, "divmod()")
-
-PyObject *
-PyNumber_Add(PyObject *v, PyObject *w)
-{
- PyObject *result = binary_op1(v, w, NB_SLOT(nb_add));
- if (result == Py_NotImplemented) {
- PySequenceMethods *m = v->ob_type->tp_as_sequence;
- Py_DECREF(result);
- if (m && m->sq_concat) {
- return (*m->sq_concat)(v, w);
- }
- result = binop_type_error(v, w, "+");
- }
- return result;
-}
-
-static PyObject *
-sequence_repeat(ssizeargfunc repeatfunc, PyObject *seq, PyObject *n)
-{
- Py_ssize_t count;
- if (PyIndex_Check(n)) {
- count = PyNumber_AsSsize_t(n, PyExc_OverflowError);
- if (count == -1 && PyErr_Occurred())
- return NULL;
- }
- else {
- return type_error("can't multiply sequence by "
- "non-int of type '%.200s'", n);
- }
- return (*repeatfunc)(seq, count);
-}
-
-PyObject *
-PyNumber_Multiply(PyObject *v, PyObject *w)
-{
- PyObject *result = binary_op1(v, w, NB_SLOT(nb_multiply));
- if (result == Py_NotImplemented) {
- PySequenceMethods *mv = v->ob_type->tp_as_sequence;
- PySequenceMethods *mw = w->ob_type->tp_as_sequence;
- Py_DECREF(result);
- if (mv && mv->sq_repeat) {
- return sequence_repeat(mv->sq_repeat, v, w);
- }
- else if (mw && mw->sq_repeat) {
- return sequence_repeat(mw->sq_repeat, w, v);
- }
- result = binop_type_error(v, w, "*");
- }
- return result;
-}
-
-PyObject *
-PyNumber_FloorDivide(PyObject *v, PyObject *w)
-{
- /* XXX tp_flags test */
- return binary_op(v, w, NB_SLOT(nb_floor_divide), "//");
-}
-
-PyObject *
-PyNumber_TrueDivide(PyObject *v, PyObject *w)
-{
- /* XXX tp_flags test */
- return binary_op(v, w, NB_SLOT(nb_true_divide), "/");
-}
-
-PyObject *
-PyNumber_Remainder(PyObject *v, PyObject *w)
-{
- return binary_op(v, w, NB_SLOT(nb_remainder), "%");
-}
-
-PyObject *
-PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
-{
- return ternary_op(v, w, z, NB_SLOT(nb_power), "** or pow()");
-}
-
-/* Binary in-place operators */
-
-/* The in-place operators are defined to fall back to the 'normal',
- non in-place operations, if the in-place methods are not in place.
-
- - If the left hand object has the appropriate struct members, and
- they are filled, call the appropriate function and return the
- result. No coercion is done on the arguments; the left-hand object
- is the one the operation is performed on, and it's up to the
- function to deal with the right-hand object.
-
- - Otherwise, in-place modification is not supported. Handle it exactly as
- a non in-place operation of the same kind.
-
- */
-
-#define HASINPLACE(t) \
- PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)
-
-static PyObject *
-binary_iop1(PyObject *v, PyObject *w, const int iop_slot, const int op_slot)
-{
- PyNumberMethods *mv = v->ob_type->tp_as_number;
- if (mv != NULL && HASINPLACE(v)) {
- binaryfunc slot = NB_BINOP(mv, iop_slot);
- if (slot) {
- PyObject *x = (slot)(v, w);
- if (x != Py_NotImplemented) {
- return x;
- }
- Py_DECREF(x);
- }
- }
- return binary_op1(v, w, op_slot);
-}
-
-static PyObject *
-binary_iop(PyObject *v, PyObject *w, const int iop_slot, const int op_slot,
- const char *op_name)
-{
- PyObject *result = binary_iop1(v, w, iop_slot, op_slot);
- if (result == Py_NotImplemented) {
- Py_DECREF(result);
- return binop_type_error(v, w, op_name);
- }
- return result;
-}
-
-#define INPLACE_BINOP(func, iop, op, op_name) \
- PyObject * \
- func(PyObject *v, PyObject *w) { \
- return binary_iop(v, w, NB_SLOT(iop), NB_SLOT(op), op_name); \
- }
-
-INPLACE_BINOP(PyNumber_InPlaceOr, nb_inplace_or, nb_or, "|=")
-INPLACE_BINOP(PyNumber_InPlaceXor, nb_inplace_xor, nb_xor, "^=")
-INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=")
-INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=")
-INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=")
-INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=")
-INPLACE_BINOP(PyNumber_InPlaceDivide, nb_inplace_divide, nb_divide, "/=")
-
-PyObject *
-PyNumber_InPlaceFloorDivide(PyObject *v, PyObject *w)
-{
- /* XXX tp_flags test */
- return binary_iop(v, w, NB_SLOT(nb_inplace_floor_divide),
- NB_SLOT(nb_floor_divide), "//=");
-}
-
-PyObject *
-PyNumber_InPlaceTrueDivide(PyObject *v, PyObject *w)
-{
- /* XXX tp_flags test */
- return binary_iop(v, w, NB_SLOT(nb_inplace_true_divide),
- NB_SLOT(nb_true_divide), "/=");
-}
-
-PyObject *
-PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
-{
- PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_add),
- NB_SLOT(nb_add));
- if (result == Py_NotImplemented) {
- PySequenceMethods *m = v->ob_type->tp_as_sequence;
- Py_DECREF(result);
- if (m != NULL) {
- binaryfunc f = NULL;
- if (HASINPLACE(v))
- f = m->sq_inplace_concat;
- if (f == NULL)
- f = m->sq_concat;
- if (f != NULL)
- return (*f)(v, w);
- }
- result = binop_type_error(v, w, "+=");
- }
- return result;
-}
-
-PyObject *
-PyNumber_InPlaceMultiply(PyObject *v, PyObject *w)
-{
- PyObject *result = binary_iop1(v, w, NB_SLOT(nb_inplace_multiply),
- NB_SLOT(nb_multiply));
- if (result == Py_NotImplemented) {
- ssizeargfunc f = NULL;
- PySequenceMethods *mv = v->ob_type->tp_as_sequence;
- PySequenceMethods *mw = w->ob_type->tp_as_sequence;
- Py_DECREF(result);
- if (mv != NULL) {
- if (HASINPLACE(v))
- f = mv->sq_inplace_repeat;
- if (f == NULL)
- f = mv->sq_repeat;
- if (f != NULL)
- return sequence_repeat(f, v, w);
- }
- else if (mw != NULL) {
- /* Note that the right hand operand should not be
- * mutated in this case so sq_inplace_repeat is not
- * used. */
- if (mw->sq_repeat)
- return sequence_repeat(mw->sq_repeat, w, v);
- }
- result = binop_type_error(v, w, "*=");
- }
- return result;
-}
-
-PyObject *
-PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
-{
- return binary_iop(v, w, NB_SLOT(nb_inplace_remainder),
- NB_SLOT(nb_remainder), "%=");
-}
-
-PyObject *
-PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
-{
- if (HASINPLACE(v) && v->ob_type->tp_as_number &&
- v->ob_type->tp_as_number->nb_inplace_power != NULL) {
- return ternary_op(v, w, z, NB_SLOT(nb_inplace_power), "**=");
- }
- else {
- return ternary_op(v, w, z, NB_SLOT(nb_power), "**=");
- }
-}
-
-
-/* Unary operators and functions */
-
-PyObject *
-PyNumber_Negative(PyObject *o)
-{
- PyNumberMethods *m;
-
- if (o == NULL)
- return null_error();
- m = o->ob_type->tp_as_number;
- if (m && m->nb_negative)
- return (*m->nb_negative)(o);
-
- return type_error("bad operand type for unary -: '%.200s'", o);
-}
-
-PyObject *
-PyNumber_Positive(PyObject *o)
-{
- PyNumberMethods *m;
-
- if (o == NULL)
- return null_error();
- m = o->ob_type->tp_as_number;
- if (m && m->nb_positive)
- return (*m->nb_positive)(o);
-
- return type_error("bad operand type for unary +: '%.200s'", o);
-}
-
-PyObject *
-PyNumber_Invert(PyObject *o)
-{
- PyNumberMethods *m;
-
- if (o == NULL)
- return null_error();
- m = o->ob_type->tp_as_number;
- if (m && m->nb_invert)
- return (*m->nb_invert)(o);
-
- return type_error("bad operand type for unary ~: '%.200s'", o);
-}
-
-PyObject *
-PyNumber_Absolute(PyObject *o)
-{
- PyNumberMethods *m;
-
- if (o == NULL)
- return null_error();
- m = o->ob_type->tp_as_number;
- if (m && m->nb_absolute)
- return m->nb_absolute(o);
-
- return type_error("bad operand type for abs(): '%.200s'", o);
-}
-
-/* Add a check for embedded NULL-bytes in the argument. */
-static PyObject *
-int_from_string(const char *s, Py_ssize_t len)
-{
- char *end;
- PyObject *x;
-
- x = PyInt_FromString((char*)s, &end, 10);
- if (x == NULL)
- return NULL;
- if (end != s + len) {
- PyErr_SetString(PyExc_ValueError,
- "null byte in argument for int()");
- Py_DECREF(x);
- return NULL;
- }
- return x;
-}
-
-/* Return a Python Int or Long from the object item
- Raise TypeError if the result is not an int-or-long
- or if the object cannot be interpreted as an index.
-*/
-PyObject *
-PyNumber_Index(PyObject *item)
-{
- PyObject *result = NULL;
- if (item == NULL)
- return null_error();
- if (PyInt_Check(item) || PyLong_Check(item)) {
- Py_INCREF(item);
- return item;
- }
- if (PyIndex_Check(item)) {
- result = item->ob_type->tp_as_number->nb_index(item);
- if (result &&
- !PyInt_Check(result) && !PyLong_Check(result)) {
- PyErr_Format(PyExc_TypeError,
- "__index__ returned non-(int,long) " \
- "(type %.200s)",
- result->ob_type->tp_name);
- Py_DECREF(result);
- return NULL;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "'%.200s' object cannot be interpreted "
- "as an index", item->ob_type->tp_name);
- }
- return result;
-}
-
-/* Return an error on Overflow only if err is not NULL*/
-
-Py_ssize_t
-PyNumber_AsSsize_t(PyObject *item, PyObject *err)
-{
- Py_ssize_t result;
- PyObject *runerr;
- PyObject *value = PyNumber_Index(item);
- if (value == NULL)
- return -1;
-
- /* We're done if PyInt_AsSsize_t() returns without error. */
- result = PyInt_AsSsize_t(value);
- if (result != -1 || !(runerr = PyErr_Occurred()))
- goto finish;
-
- /* Error handling code -- only manage OverflowError differently */
- if (!PyErr_GivenExceptionMatches(runerr, PyExc_OverflowError))
- goto finish;
-
- PyErr_Clear();
- /* If no error-handling desired then the default clipping
- is sufficient.
- */
- if (!err) {
- assert(PyLong_Check(value));
- /* Whether or not it is less than or equal to
- zero is determined by the sign of ob_size
- */
- if (_PyLong_Sign(value) < 0)
- result = PY_SSIZE_T_MIN;
- else
- result = PY_SSIZE_T_MAX;
- }
- else {
- /* Otherwise replace the error with caller's error object. */
- PyErr_Format(err,
- "cannot fit '%.200s' into an index-sized integer",
- item->ob_type->tp_name);
- }
-
- finish:
- Py_DECREF(value);
- return result;
-}
-
-
-PyObject *
-PyNumber_Int(PyObject *o)
-{
- PyNumberMethods *m;
- const char *buffer;
- Py_ssize_t buffer_len;
-
- if (o == NULL)
- return null_error();
- if (PyInt_CheckExact(o)) {
- Py_INCREF(o);
- return o;
- }
- m = o->ob_type->tp_as_number;
- if (m && m->nb_int) { /* This should include subclasses of int */
- PyObject *res = m->nb_int(o);
- if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
- PyErr_Format(PyExc_TypeError,
- "__int__ returned non-int (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
- }
- if (PyInt_Check(o)) { /* A int subclass without nb_int */
- PyIntObject *io = (PyIntObject*)o;
- return PyInt_FromLong(io->ob_ival);
- }
- if (PyString_Check(o))
- return int_from_string(PyString_AS_STRING(o),
- PyString_GET_SIZE(o));
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(o))
- return PyInt_FromUnicode(PyUnicode_AS_UNICODE(o),
- PyUnicode_GET_SIZE(o),
- 10);
-#endif
- if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
- return int_from_string((char*)buffer, buffer_len);
-
- return type_error("int() argument must be a string or a "
- "number, not '%.200s'", o);
-}
-
-/* Add a check for embedded NULL-bytes in the argument. */
-static PyObject *
-long_from_string(const char *s, Py_ssize_t len)
-{
- char *end;
- PyObject *x;
-
- x = PyLong_FromString((char*)s, &end, 10);
- if (x == NULL)
- return NULL;
- if (end != s + len) {
- PyErr_SetString(PyExc_ValueError,
- "null byte in argument for long()");
- Py_DECREF(x);
- return NULL;
- }
- return x;
-}
-
-PyObject *
-PyNumber_Long(PyObject *o)
-{
- PyNumberMethods *m;
- const char *buffer;
- Py_ssize_t buffer_len;
-
- if (o == NULL)
- return null_error();
- m = o->ob_type->tp_as_number;
- if (m && m->nb_long) { /* This should include subclasses of long */
- PyObject *res = m->nb_long(o);
- if (res && (!PyInt_Check(res) && !PyLong_Check(res))) {
- PyErr_Format(PyExc_TypeError,
- "__long__ returned non-long (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
- }
- if (PyLong_Check(o)) /* A long subclass without nb_long */
- return _PyLong_Copy((PyLongObject *)o);
- if (PyString_Check(o))
- /* need to do extra error checking that PyLong_FromString()
- * doesn't do. In particular long('9.5') must raise an
- * exception, not truncate the float.
- */
- return long_from_string(PyString_AS_STRING(o),
- PyString_GET_SIZE(o));
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(o))
- /* The above check is done in PyLong_FromUnicode(). */
- return PyLong_FromUnicode(PyUnicode_AS_UNICODE(o),
- PyUnicode_GET_SIZE(o),
- 10);
-#endif
- if (!PyObject_AsCharBuffer(o, &buffer, &buffer_len))
- return long_from_string(buffer, buffer_len);
-
- return type_error("long() argument must be a string or a "
- "number, not '%.200s'", o);
-}
-
-PyObject *
-PyNumber_Float(PyObject *o)
-{
- PyNumberMethods *m;
-
- if (o == NULL)
- return null_error();
- m = o->ob_type->tp_as_number;
- if (m && m->nb_float) { /* This should include subclasses of float */
- PyObject *res = m->nb_float(o);
- if (res && !PyFloat_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "__float__ returned non-float (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
- }
- if (PyFloat_Check(o)) { /* A float subclass with nb_float == NULL */
- PyFloatObject *po = (PyFloatObject *)o;
- return PyFloat_FromDouble(po->ob_fval);
- }
- return PyFloat_FromString(o, NULL);
-}
-
-/* Operations on sequences */
-
-int
-PySequence_Check(PyObject *s)
-{
- if (s && PyInstance_Check(s))
- return PyObject_HasAttrString(s, "__getitem__");
- if (PyObject_IsInstance(s, (PyObject *)&PyDict_Type))
- return 0;
- return s != NULL && s->ob_type->tp_as_sequence &&
- s->ob_type->tp_as_sequence->sq_item != NULL;
-}
-
-Py_ssize_t
-PySequence_Size(PyObject *s)
-{
- PySequenceMethods *m;
-
- if (s == NULL) {
- null_error();
- return -1;
- }
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_length)
- return m->sq_length(s);
-
- type_error("object of type '%.200s' has no len()", s);
- return -1;
-}
-
-#undef PySequence_Length
-Py_ssize_t
-PySequence_Length(PyObject *s)
-{
- return PySequence_Size(s);
-}
-#define PySequence_Length PySequence_Size
-
-PyObject *
-PySequence_Concat(PyObject *s, PyObject *o)
-{
- PySequenceMethods *m;
-
- if (s == NULL || o == NULL)
- return null_error();
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_concat)
- return m->sq_concat(s, o);
-
- /* Instances of user classes defining an __add__() method only
- have an nb_add slot, not an sq_concat slot. So we fall back
- to nb_add if both arguments appear to be sequences. */
- if (PySequence_Check(s) && PySequence_Check(o)) {
- PyObject *result = binary_op1(s, o, NB_SLOT(nb_add));
- if (result != Py_NotImplemented)
- return result;
- Py_DECREF(result);
- }
- return type_error("'%.200s' object can't be concatenated", s);
-}
-
-PyObject *
-PySequence_Repeat(PyObject *o, Py_ssize_t count)
-{
- PySequenceMethods *m;
-
- if (o == NULL)
- return null_error();
-
- m = o->ob_type->tp_as_sequence;
- if (m && m->sq_repeat)
- return m->sq_repeat(o, count);
-
- /* Instances of user classes defining a __mul__() method only
- have an nb_multiply slot, not an sq_repeat slot. so we fall back
- to nb_multiply if o appears to be a sequence. */
- if (PySequence_Check(o)) {
- PyObject *n, *result;
- n = PyInt_FromSsize_t(count);
- if (n == NULL)
- return NULL;
- result = binary_op1(o, n, NB_SLOT(nb_multiply));
- Py_DECREF(n);
- if (result != Py_NotImplemented)
- return result;
- Py_DECREF(result);
- }
- return type_error("'%.200s' object can't be repeated", o);
-}
-
-PyObject *
-PySequence_InPlaceConcat(PyObject *s, PyObject *o)
-{
- PySequenceMethods *m;
-
- if (s == NULL || o == NULL)
- return null_error();
-
- m = s->ob_type->tp_as_sequence;
- if (m && HASINPLACE(s) && m->sq_inplace_concat)
- return m->sq_inplace_concat(s, o);
- if (m && m->sq_concat)
- return m->sq_concat(s, o);
-
- if (PySequence_Check(s) && PySequence_Check(o)) {
- PyObject *result = binary_iop1(s, o, NB_SLOT(nb_inplace_add),
- NB_SLOT(nb_add));
- if (result != Py_NotImplemented)
- return result;
- Py_DECREF(result);
- }
- return type_error("'%.200s' object can't be concatenated", s);
-}
-
-PyObject *
-PySequence_InPlaceRepeat(PyObject *o, Py_ssize_t count)
-{
- PySequenceMethods *m;
-
- if (o == NULL)
- return null_error();
-
- m = o->ob_type->tp_as_sequence;
- if (m && HASINPLACE(o) && m->sq_inplace_repeat)
- return m->sq_inplace_repeat(o, count);
- if (m && m->sq_repeat)
- return m->sq_repeat(o, count);
-
- if (PySequence_Check(o)) {
- PyObject *n, *result;
- n = PyInt_FromSsize_t(count);
- if (n == NULL)
- return NULL;
- result = binary_iop1(o, n, NB_SLOT(nb_inplace_multiply),
- NB_SLOT(nb_multiply));
- Py_DECREF(n);
- if (result != Py_NotImplemented)
- return result;
- Py_DECREF(result);
- }
- return type_error("'%.200s' object can't be repeated", o);
-}
-
-PyObject *
-PySequence_GetItem(PyObject *s, Py_ssize_t i)
-{
- PySequenceMethods *m;
-
- if (s == NULL)
- return null_error();
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_item) {
- if (i < 0) {
- if (m->sq_length) {
- Py_ssize_t l = (*m->sq_length)(s);
- if (l < 0)
- return NULL;
- i += l;
- }
- }
- return m->sq_item(s, i);
- }
-
- return type_error("'%.200s' object is unindexable", s);
-}
-
-PyObject *
-PySequence_GetSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2)
-{
- PySequenceMethods *m;
- PyMappingMethods *mp;
-
- if (!s) return null_error();
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_slice) {
- if (i1 < 0 || i2 < 0) {
- if (m->sq_length) {
- Py_ssize_t l = (*m->sq_length)(s);
- if (l < 0)
- return NULL;
- if (i1 < 0)
- i1 += l;
- if (i2 < 0)
- i2 += l;
- }
- }
- return m->sq_slice(s, i1, i2);
- } else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_subscript) {
- PyObject *res;
- PyObject *slice = _PySlice_FromIndices(i1, i2);
- if (!slice)
- return NULL;
- res = mp->mp_subscript(s, slice);
- Py_DECREF(slice);
- return res;
- }
-
- return type_error("'%.200s' object is unsliceable", s);
-}
-
-int
-PySequence_SetItem(PyObject *s, Py_ssize_t i, PyObject *o)
-{
- PySequenceMethods *m;
-
- if (s == NULL) {
- null_error();
- return -1;
- }
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_ass_item) {
- if (i < 0) {
- if (m->sq_length) {
- Py_ssize_t l = (*m->sq_length)(s);
- if (l < 0)
- return -1;
- i += l;
- }
- }
- return m->sq_ass_item(s, i, o);
- }
-
- type_error("'%.200s' object does not support item assignment", s);
- return -1;
-}
-
-int
-PySequence_DelItem(PyObject *s, Py_ssize_t i)
-{
- PySequenceMethods *m;
-
- if (s == NULL) {
- null_error();
- return -1;
- }
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_ass_item) {
- if (i < 0) {
- if (m->sq_length) {
- Py_ssize_t l = (*m->sq_length)(s);
- if (l < 0)
- return -1;
- i += l;
- }
- }
- return m->sq_ass_item(s, i, (PyObject *)NULL);
- }
-
- type_error("'%.200s' object doesn't support item deletion", s);
- return -1;
-}
-
-int
-PySequence_SetSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2, PyObject *o)
-{
- PySequenceMethods *m;
- PyMappingMethods *mp;
-
- if (s == NULL) {
- null_error();
- return -1;
- }
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_ass_slice) {
- if (i1 < 0 || i2 < 0) {
- if (m->sq_length) {
- Py_ssize_t l = (*m->sq_length)(s);
- if (l < 0)
- return -1;
- if (i1 < 0)
- i1 += l;
- if (i2 < 0)
- i2 += l;
- }
- }
- return m->sq_ass_slice(s, i1, i2, o);
- } else if ((mp = s->ob_type->tp_as_mapping) && mp->mp_ass_subscript) {
- int res;
- PyObject *slice = _PySlice_FromIndices(i1, i2);
- if (!slice)
- return -1;
- res = mp->mp_ass_subscript(s, slice, o);
- Py_DECREF(slice);
- return res;
- }
-
- type_error("'%.200s' object doesn't support slice assignment", s);
- return -1;
-}
-
-int
-PySequence_DelSlice(PyObject *s, Py_ssize_t i1, Py_ssize_t i2)
-{
- PySequenceMethods *m;
-
- if (s == NULL) {
- null_error();
- return -1;
- }
-
- m = s->ob_type->tp_as_sequence;
- if (m && m->sq_ass_slice) {
- if (i1 < 0 || i2 < 0) {
- if (m->sq_length) {
- Py_ssize_t l = (*m->sq_length)(s);
- if (l < 0)
- return -1;
- if (i1 < 0)
- i1 += l;
- if (i2 < 0)
- i2 += l;
- }
- }
- return m->sq_ass_slice(s, i1, i2, (PyObject *)NULL);
- }
- type_error("'%.200s' object doesn't support slice deletion", s);
- return -1;
-}
-
-PyObject *
-PySequence_Tuple(PyObject *v)
-{
- PyObject *it; /* iter(v) */
- Py_ssize_t n; /* guess for result tuple size */
- PyObject *result;
- Py_ssize_t j;
-
- if (v == NULL)
- return null_error();
-
- /* Special-case the common tuple and list cases, for efficiency. */
- if (PyTuple_CheckExact(v)) {
- /* Note that we can't know whether it's safe to return
- a tuple *subclass* instance as-is, hence the restriction
- to exact tuples here. In contrast, lists always make
- a copy, so there's no need for exactness below. */
- Py_INCREF(v);
- return v;
- }
- if (PyList_Check(v))
- return PyList_AsTuple(v);
-
- /* Get iterator. */
- it = PyObject_GetIter(v);
- if (it == NULL)
- return NULL;
-
- /* Guess result size and allocate space. */
- n = _PyObject_LengthHint(v);
- if (n < 0) {
- if (!PyErr_ExceptionMatches(PyExc_TypeError) &&
- !PyErr_ExceptionMatches(PyExc_AttributeError)) {
- Py_DECREF(it);
- return NULL;
- }
- PyErr_Clear();
- n = 10; /* arbitrary */
- }
- result = PyTuple_New(n);
- if (result == NULL)
- goto Fail;
-
- /* Fill the tuple. */
- for (j = 0; ; ++j) {
- PyObject *item = PyIter_Next(it);
- if (item == NULL) {
- if (PyErr_Occurred())
- goto Fail;
- break;
- }
- if (j >= n) {
- Py_ssize_t oldn = n;
- /* The over-allocation strategy can grow a bit faster
- than for lists because unlike lists the
- over-allocation isn't permanent -- we reclaim
- the excess before the end of this routine.
- So, grow by ten and then add 25%.
- */
- n += 10;
- n += n >> 2;
- if (n < oldn) {
- /* Check for overflow */
- PyErr_NoMemory();
- Py_DECREF(item);
- goto Fail;
- }
- if (_PyTuple_Resize(&result, n) != 0) {
- Py_DECREF(item);
- goto Fail;
- }
- }
- PyTuple_SET_ITEM(result, j, item);
- }
-
- /* Cut tuple back if guess was too large. */
- if (j < n &&
- _PyTuple_Resize(&result, j) != 0)
- goto Fail;
-
- Py_DECREF(it);
- return result;
-
-Fail:
- Py_XDECREF(result);
- Py_DECREF(it);
- return NULL;
-}
-
-PyObject *
-PySequence_List(PyObject *v)
-{
- PyObject *result; /* result list */
- PyObject *rv; /* return value from PyList_Extend */
-
- if (v == NULL)
- return null_error();
-
- result = PyList_New(0);
- if (result == NULL)
- return NULL;
-
- rv = _PyList_Extend((PyListObject *)result, v);
- if (rv == NULL) {
- Py_DECREF(result);
- return NULL;
- }
- Py_DECREF(rv);
- return result;
-}
-
-PyObject *
-PySequence_Fast(PyObject *v, const char *m)
-{
- PyObject *it;
-
- if (v == NULL)
- return null_error();
-
- if (PyList_CheckExact(v) || PyTuple_CheckExact(v)) {
- Py_INCREF(v);
- return v;
- }
-
- it = PyObject_GetIter(v);
- if (it == NULL) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_SetString(PyExc_TypeError, m);
- return NULL;
- }
-
- v = PySequence_List(it);
- Py_DECREF(it);
-
- return v;
-}
-
-/* Iterate over seq. Result depends on the operation:
- PY_ITERSEARCH_COUNT: -1 if error, else # of times obj appears in seq.
- PY_ITERSEARCH_INDEX: 0-based index of first occurence of obj in seq;
- set ValueError and return -1 if none found; also return -1 on error.
- Py_ITERSEARCH_CONTAINS: return 1 if obj in seq, else 0; -1 on error.
-*/
-Py_ssize_t
-_PySequence_IterSearch(PyObject *seq, PyObject *obj, int operation)
-{
- Py_ssize_t n;
- int wrapped; /* for PY_ITERSEARCH_INDEX, true iff n wrapped around */
- PyObject *it; /* iter(seq) */
-
- if (seq == NULL || obj == NULL) {
- null_error();
- return -1;
- }
-
- it = PyObject_GetIter(seq);
- if (it == NULL) {
- type_error("argument of type '%.200s' is not iterable", seq);
- return -1;
- }
-
- n = wrapped = 0;
- for (;;) {
- int cmp;
- PyObject *item = PyIter_Next(it);
- if (item == NULL) {
- if (PyErr_Occurred())
- goto Fail;
- break;
- }
-
- cmp = PyObject_RichCompareBool(obj, item, Py_EQ);
- Py_DECREF(item);
- if (cmp < 0)
- goto Fail;
- if (cmp > 0) {
- switch (operation) {
- case PY_ITERSEARCH_COUNT:
- if (n == PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "count exceeds C integer size");
- goto Fail;
- }
- ++n;
- break;
-
- case PY_ITERSEARCH_INDEX:
- if (wrapped) {
- PyErr_SetString(PyExc_OverflowError,
- "index exceeds C integer size");
- goto Fail;
- }
- goto Done;
-
- case PY_ITERSEARCH_CONTAINS:
- n = 1;
- goto Done;
-
- default:
- assert(!"unknown operation");
- }
- }
-
- if (operation == PY_ITERSEARCH_INDEX) {
- if (n == PY_SSIZE_T_MAX)
- wrapped = 1;
- ++n;
- }
- }
-
- if (operation != PY_ITERSEARCH_INDEX)
- goto Done;
-
- PyErr_SetString(PyExc_ValueError,
- "sequence.index(x): x not in sequence");
- /* fall into failure code */
-Fail:
- n = -1;
- /* fall through */
-Done:
- Py_DECREF(it);
- return n;
-
-}
-
-/* Return # of times o appears in s. */
-Py_ssize_t
-PySequence_Count(PyObject *s, PyObject *o)
-{
- return _PySequence_IterSearch(s, o, PY_ITERSEARCH_COUNT);
-}
-
-/* Return -1 if error; 1 if ob in seq; 0 if ob not in seq.
- * Use sq_contains if possible, else defer to _PySequence_IterSearch().
- */
-int
-PySequence_Contains(PyObject *seq, PyObject *ob)
-{
- Py_ssize_t result;
- if (PyType_HasFeature(seq->ob_type, Py_TPFLAGS_HAVE_SEQUENCE_IN)) {
- PySequenceMethods *sqm = seq->ob_type->tp_as_sequence;
- if (sqm != NULL && sqm->sq_contains != NULL)
- return (*sqm->sq_contains)(seq, ob);
- }
- result = _PySequence_IterSearch(seq, ob, PY_ITERSEARCH_CONTAINS);
- return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);
-}
-
-/* Backwards compatibility */
-#undef PySequence_In
-int
-PySequence_In(PyObject *w, PyObject *v)
-{
- return PySequence_Contains(w, v);
-}
-
-Py_ssize_t
-PySequence_Index(PyObject *s, PyObject *o)
-{
- return _PySequence_IterSearch(s, o, PY_ITERSEARCH_INDEX);
-}
-
-/* Operations on mappings */
-
-int
-PyMapping_Check(PyObject *o)
-{
- if (o && PyInstance_Check(o))
- return PyObject_HasAttrString(o, "__getitem__");
-
- return o && o->ob_type->tp_as_mapping &&
- o->ob_type->tp_as_mapping->mp_subscript &&
- !(o->ob_type->tp_as_sequence &&
- o->ob_type->tp_as_sequence->sq_slice);
-}
-
-Py_ssize_t
-PyMapping_Size(PyObject *o)
-{
- PyMappingMethods *m;
-
- if (o == NULL) {
- null_error();
- return -1;
- }
-
- m = o->ob_type->tp_as_mapping;
- if (m && m->mp_length)
- return m->mp_length(o);
-
- type_error("object of type '%.200s' has no len()", o);
- return -1;
-}
-
-#undef PyMapping_Length
-Py_ssize_t
-PyMapping_Length(PyObject *o)
-{
- return PyMapping_Size(o);
-}
-#define PyMapping_Length PyMapping_Size
-
-PyObject *
-PyMapping_GetItemString(PyObject *o, char *key)
-{
- PyObject *okey, *r;
-
- if (key == NULL)
- return null_error();
-
- okey = PyString_FromString(key);
- if (okey == NULL)
- return NULL;
- r = PyObject_GetItem(o, okey);
- Py_DECREF(okey);
- return r;
-}
-
-int
-PyMapping_SetItemString(PyObject *o, char *key, PyObject *value)
-{
- PyObject *okey;
- int r;
-
- if (key == NULL) {
- null_error();
- return -1;
- }
-
- okey = PyString_FromString(key);
- if (okey == NULL)
- return -1;
- r = PyObject_SetItem(o, okey, value);
- Py_DECREF(okey);
- return r;
-}
-
-int
-PyMapping_HasKeyString(PyObject *o, char *key)
-{
- PyObject *v;
-
- v = PyMapping_GetItemString(o, key);
- if (v) {
- Py_DECREF(v);
- return 1;
- }
- PyErr_Clear();
- return 0;
-}
-
-int
-PyMapping_HasKey(PyObject *o, PyObject *key)
-{
- PyObject *v;
-
- v = PyObject_GetItem(o, key);
- if (v) {
- Py_DECREF(v);
- return 1;
- }
- PyErr_Clear();
- return 0;
-}
-
-/* Operations on callable objects */
-
-/* XXX PyCallable_Check() is in object.c */
-
-PyObject *
-PyObject_CallObject(PyObject *o, PyObject *a)
-{
- return PyEval_CallObjectWithKeywords(o, a, NULL);
-}
-
-PyObject *
-PyObject_Call(PyObject *func, PyObject *arg, PyObject *kw)
-{
- ternaryfunc call;
-
- if ((call = func->ob_type->tp_call) != NULL) {
- PyObject *result = (*call)(func, arg, kw);
- if (result == NULL && !PyErr_Occurred())
- PyErr_SetString(
- PyExc_SystemError,
- "NULL result without error in PyObject_Call");
- return result;
- }
- PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable",
- func->ob_type->tp_name);
- return NULL;
-}
-
-static PyObject*
-call_function_tail(PyObject *callable, PyObject *args)
-{
- PyObject *retval;
-
- if (args == NULL)
- return NULL;
-
- if (!PyTuple_Check(args)) {
- PyObject *a;
-
- a = PyTuple_New(1);
- if (a == NULL) {
- Py_DECREF(args);
- return NULL;
- }
- PyTuple_SET_ITEM(a, 0, args);
- args = a;
- }
- retval = PyObject_Call(callable, args, NULL);
-
- Py_DECREF(args);
-
- return retval;
-}
-
-PyObject *
-PyObject_CallFunction(PyObject *callable, char *format, ...)
-{
- va_list va;
- PyObject *args;
-
- if (callable == NULL)
- return null_error();
-
- if (format && *format) {
- va_start(va, format);
- args = Py_VaBuildValue(format, va);
- va_end(va);
- }
- else
- args = PyTuple_New(0);
-
- return call_function_tail(callable, args);
-}
-
-PyObject *
-_PyObject_CallFunction_SizeT(PyObject *callable, char *format, ...)
-{
- va_list va;
- PyObject *args;
-
- if (callable == NULL)
- return null_error();
-
- if (format && *format) {
- va_start(va, format);
- args = _Py_VaBuildValue_SizeT(format, va);
- va_end(va);
- }
- else
- args = PyTuple_New(0);
-
- return call_function_tail(callable, args);
-}
-
-PyObject *
-PyObject_CallMethod(PyObject *o, char *name, char *format, ...)
-{
- va_list va;
- PyObject *args;
- PyObject *func = NULL;
- PyObject *retval = NULL;
-
- if (o == NULL || name == NULL)
- return null_error();
-
- func = PyObject_GetAttrString(o, name);
- if (func == NULL) {
- PyErr_SetString(PyExc_AttributeError, name);
- return 0;
- }
-
- if (!PyCallable_Check(func)) {
- type_error("attribute of type '%.200s' is not callable", func);
- goto exit;
- }
-
- if (format && *format) {
- va_start(va, format);
- args = Py_VaBuildValue(format, va);
- va_end(va);
- }
- else
- args = PyTuple_New(0);
-
- retval = call_function_tail(func, args);
-
- exit:
- /* args gets consumed in call_function_tail */
- Py_XDECREF(func);
-
- return retval;
-}
-
-PyObject *
-_PyObject_CallMethod_SizeT(PyObject *o, char *name, char *format, ...)
-{
- va_list va;
- PyObject *args;
- PyObject *func = NULL;
- PyObject *retval = NULL;
-
- if (o == NULL || name == NULL)
- return null_error();
-
- func = PyObject_GetAttrString(o, name);
- if (func == NULL) {
- PyErr_SetString(PyExc_AttributeError, name);
- return 0;
- }
-
- if (!PyCallable_Check(func)) {
- type_error("attribute of type '%.200s' is not callable", func);
- goto exit;
- }
-
- if (format && *format) {
- va_start(va, format);
- args = _Py_VaBuildValue_SizeT(format, va);
- va_end(va);
- }
- else
- args = PyTuple_New(0);
-
- retval = call_function_tail(func, args);
-
- exit:
- /* args gets consumed in call_function_tail */
- Py_XDECREF(func);
-
- return retval;
-}
-
-
-static PyObject *
-objargs_mktuple(va_list va)
-{
- int i, n = 0;
- va_list countva;
- PyObject *result, *tmp;
-
-#ifdef VA_LIST_IS_ARRAY
- memcpy(countva, va, sizeof(va_list));
-#else
-#ifdef __va_copy
- __va_copy(countva, va);
-#else
- countva = va;
-#endif
-#endif
-
- while (((PyObject *)va_arg(countva, PyObject *)) != NULL)
- ++n;
- result = PyTuple_New(n);
- if (result != NULL && n > 0) {
- for (i = 0; i < n; ++i) {
- tmp = (PyObject *)va_arg(va, PyObject *);
- PyTuple_SET_ITEM(result, i, tmp);
- Py_INCREF(tmp);
- }
- }
- return result;
-}
-
-PyObject *
-PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...)
-{
- PyObject *args, *tmp;
- va_list vargs;
-
- if (callable == NULL || name == NULL)
- return null_error();
-
- callable = PyObject_GetAttr(callable, name);
- if (callable == NULL)
- return NULL;
-
- /* count the args */
- va_start(vargs, name);
- args = objargs_mktuple(vargs);
- va_end(vargs);
- if (args == NULL) {
- Py_DECREF(callable);
- return NULL;
- }
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
- Py_DECREF(callable);
-
- return tmp;
-}
-
-PyObject *
-PyObject_CallFunctionObjArgs(PyObject *callable, ...)
-{
- PyObject *args, *tmp;
- va_list vargs;
-
- if (callable == NULL)
- return null_error();
-
- /* count the args */
- va_start(vargs, callable);
- args = objargs_mktuple(vargs);
- va_end(vargs);
- if (args == NULL)
- return NULL;
- tmp = PyObject_Call(callable, args, NULL);
- Py_DECREF(args);
-
- return tmp;
-}
-
-
-/* isinstance(), issubclass() */
-
-/* abstract_get_bases() has logically 4 return states, with a sort of 0th
- * state that will almost never happen.
- *
- * 0. creating the __bases__ static string could get a MemoryError
- * 1. getattr(cls, '__bases__') could raise an AttributeError
- * 2. getattr(cls, '__bases__') could raise some other exception
- * 3. getattr(cls, '__bases__') could return a tuple
- * 4. getattr(cls, '__bases__') could return something other than a tuple
- *
- * Only state #3 is a non-error state and only it returns a non-NULL object
- * (it returns the retrieved tuple).
- *
- * Any raised AttributeErrors are masked by clearing the exception and
- * returning NULL. If an object other than a tuple comes out of __bases__,
- * then again, the return value is NULL. So yes, these two situations
- * produce exactly the same results: NULL is returned and no error is set.
- *
- * If some exception other than AttributeError is raised, then NULL is also
- * returned, but the exception is not cleared. That's because we want the
- * exception to be propagated along.
- *
- * Callers are expected to test for PyErr_Occurred() when the return value
- * is NULL to decide whether a valid exception should be propagated or not.
- * When there's no exception to propagate, it's customary for the caller to
- * set a TypeError.
- */
-static PyObject *
-abstract_get_bases(PyObject *cls)
-{
- static PyObject *__bases__ = NULL;
- PyObject *bases;
-
- if (__bases__ == NULL) {
- __bases__ = PyString_FromString("__bases__");
- if (__bases__ == NULL)
- return NULL;
- }
- bases = PyObject_GetAttr(cls, __bases__);
- if (bases == NULL) {
- if (PyErr_ExceptionMatches(PyExc_AttributeError))
- PyErr_Clear();
- return NULL;
- }
- if (!PyTuple_Check(bases)) {
- Py_DECREF(bases);
- return NULL;
- }
- return bases;
-}
-
-
-static int
-abstract_issubclass(PyObject *derived, PyObject *cls)
-{
- PyObject *bases;
- Py_ssize_t i, n;
- int r = 0;
-
-
- if (derived == cls)
- return 1;
-
- if (PyTuple_Check(cls)) {
- /* Not a general sequence -- that opens up the road to
- recursion and stack overflow. */
- n = PyTuple_GET_SIZE(cls);
- for (i = 0; i < n; i++) {
- if (derived == PyTuple_GET_ITEM(cls, i))
- return 1;
- }
- }
- bases = abstract_get_bases(derived);
- if (bases == NULL) {
- if (PyErr_Occurred())
- return -1;
- return 0;
- }
- n = PyTuple_GET_SIZE(bases);
- for (i = 0; i < n; i++) {
- r = abstract_issubclass(PyTuple_GET_ITEM(bases, i), cls);
- if (r != 0)
- break;
- }
-
- Py_DECREF(bases);
-
- return r;
-}
-
-static int
-check_class(PyObject *cls, const char *error)
-{
- PyObject *bases = abstract_get_bases(cls);
- if (bases == NULL) {
- /* Do not mask errors. */
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_TypeError, error);
- return 0;
- }
- Py_DECREF(bases);
- return -1;
-}
-
-static int
-recursive_isinstance(PyObject *inst, PyObject *cls, int recursion_depth)
-{
- PyObject *icls;
- static PyObject *__class__ = NULL;
- int retval = 0;
-
- if (__class__ == NULL) {
- __class__ = PyString_FromString("__class__");
- if (__class__ == NULL)
- return -1;
- }
-
- if (PyClass_Check(cls) && PyInstance_Check(inst)) {
- PyObject *inclass =
- (PyObject*)((PyInstanceObject*)inst)->in_class;
- retval = PyClass_IsSubclass(inclass, cls);
- }
- else if (PyType_Check(cls)) {
- retval = PyObject_TypeCheck(inst, (PyTypeObject *)cls);
- if (retval == 0) {
- PyObject *c = PyObject_GetAttr(inst, __class__);
- if (c == NULL) {
- PyErr_Clear();
- }
- else {
- if (c != (PyObject *)(inst->ob_type) &&
- PyType_Check(c))
- retval = PyType_IsSubtype(
- (PyTypeObject *)c,
- (PyTypeObject *)cls);
- Py_DECREF(c);
- }
- }
- }
- else if (PyTuple_Check(cls)) {
- Py_ssize_t i, n;
-
- if (!recursion_depth) {
- PyErr_SetString(PyExc_RuntimeError,
- "nest level of tuple too deep");
- return -1;
- }
-
- n = PyTuple_GET_SIZE(cls);
- for (i = 0; i < n; i++) {
- retval = recursive_isinstance(
- inst,
- PyTuple_GET_ITEM(cls, i),
- recursion_depth-1);
- if (retval != 0)
- break;
- }
- }
- else {
- if (!check_class(cls,
- "isinstance() arg 2 must be a class, type,"
- " or tuple of classes and types"))
- return -1;
- icls = PyObject_GetAttr(inst, __class__);
- if (icls == NULL) {
- PyErr_Clear();
- retval = 0;
- }
- else {
- retval = abstract_issubclass(icls, cls);
- Py_DECREF(icls);
- }
- }
-
- return retval;
-}
-
-int
-PyObject_IsInstance(PyObject *inst, PyObject *cls)
-{
- return recursive_isinstance(inst, cls, Py_GetRecursionLimit());
-}
-
-static int
-recursive_issubclass(PyObject *derived, PyObject *cls, int recursion_depth)
-{
- int retval;
-
- if (!PyClass_Check(derived) || !PyClass_Check(cls)) {
- if (!check_class(derived,
- "issubclass() arg 1 must be a class"))
- return -1;
-
- if (PyTuple_Check(cls)) {
- Py_ssize_t i;
- Py_ssize_t n = PyTuple_GET_SIZE(cls);
-
- if (!recursion_depth) {
- PyErr_SetString(PyExc_RuntimeError,
- "nest level of tuple too deep");
- return -1;
- }
- for (i = 0; i < n; ++i) {
- retval = recursive_issubclass(
- derived,
- PyTuple_GET_ITEM(cls, i),
- recursion_depth-1);
- if (retval != 0) {
- /* either found it, or got an error */
- return retval;
- }
- }
- return 0;
- }
- else {
- if (!check_class(cls,
- "issubclass() arg 2 must be a class"
- " or tuple of classes"))
- return -1;
- }
-
- retval = abstract_issubclass(derived, cls);
- }
- else {
- /* shortcut */
- if (!(retval = (derived == cls)))
- retval = PyClass_IsSubclass(derived, cls);
- }
-
- return retval;
-}
-
-int
-PyObject_IsSubclass(PyObject *derived, PyObject *cls)
-{
- return recursive_issubclass(derived, cls, Py_GetRecursionLimit());
-}
-
-
-PyObject *
-PyObject_GetIter(PyObject *o)
-{
- PyTypeObject *t = o->ob_type;
- getiterfunc f = NULL;
- if (PyType_HasFeature(t, Py_TPFLAGS_HAVE_ITER))
- f = t->tp_iter;
- if (f == NULL) {
- if (PySequence_Check(o))
- return PySeqIter_New(o);
- return type_error("'%.200s' object is not iterable", o);
- }
- else {
- PyObject *res = (*f)(o);
- if (res != NULL && !PyIter_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "iter() returned non-iterator "
- "of type '%.100s'",
- res->ob_type->tp_name);
- Py_DECREF(res);
- res = NULL;
- }
- return res;
- }
-}
-
-/* Return next item.
- * If an error occurs, return NULL. PyErr_Occurred() will be true.
- * If the iteration terminates normally, return NULL and clear the
- * PyExc_StopIteration exception (if it was set). PyErr_Occurred()
- * will be false.
- * Else return the next object. PyErr_Occurred() will be false.
- */
-PyObject *
-PyIter_Next(PyObject *iter)
-{
- PyObject *result;
- assert(PyIter_Check(iter));
- result = (*iter->ob_type->tp_iternext)(iter);
- if (result == NULL &&
- PyErr_Occurred() &&
- PyErr_ExceptionMatches(PyExc_StopIteration))
- PyErr_Clear();
- return result;
-}
diff --git a/sys/src/cmd/python/Objects/boolobject.c b/sys/src/cmd/python/Objects/boolobject.c
deleted file mode 100644
index 37be295ac..000000000
--- a/sys/src/cmd/python/Objects/boolobject.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Boolean type, a subtype of int */
-
-#include "Python.h"
-
-/* We need to define bool_print to override int_print */
-
-static int
-bool_print(PyBoolObject *self, FILE *fp, int flags)
-{
- fputs(self->ob_ival == 0 ? "False" : "True", fp);
- return 0;
-}
-
-/* We define bool_repr to return "False" or "True" */
-
-static PyObject *false_str = NULL;
-static PyObject *true_str = NULL;
-
-static PyObject *
-bool_repr(PyBoolObject *self)
-{
- PyObject *s;
-
- if (self->ob_ival)
- s = true_str ? true_str :
- (true_str = PyString_InternFromString("True"));
- else
- s = false_str ? false_str :
- (false_str = PyString_InternFromString("False"));
- Py_XINCREF(s);
- return s;
-}
-
-/* Function to return a bool from a C long */
-
-PyObject *PyBool_FromLong(long ok)
-{
- PyObject *result;
-
- if (ok)
- result = Py_True;
- else
- result = Py_False;
- Py_INCREF(result);
- return result;
-}
-
-/* We define bool_new to always return either Py_True or Py_False */
-
-static PyObject *
-bool_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"x", 0};
- PyObject *x = Py_False;
- long ok;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:bool", kwlist, &x))
- return NULL;
- ok = PyObject_IsTrue(x);
- if (ok < 0)
- return NULL;
- return PyBool_FromLong(ok);
-}
-
-/* Arithmetic operations redefined to return bool if both args are bool. */
-
-static PyObject *
-bool_and(PyObject *a, PyObject *b)
-{
- if (!PyBool_Check(a) || !PyBool_Check(b))
- return PyInt_Type.tp_as_number->nb_and(a, b);
- return PyBool_FromLong(
- ((PyBoolObject *)a)->ob_ival & ((PyBoolObject *)b)->ob_ival);
-}
-
-static PyObject *
-bool_or(PyObject *a, PyObject *b)
-{
- if (!PyBool_Check(a) || !PyBool_Check(b))
- return PyInt_Type.tp_as_number->nb_or(a, b);
- return PyBool_FromLong(
- ((PyBoolObject *)a)->ob_ival | ((PyBoolObject *)b)->ob_ival);
-}
-
-static PyObject *
-bool_xor(PyObject *a, PyObject *b)
-{
- if (!PyBool_Check(a) || !PyBool_Check(b))
- return PyInt_Type.tp_as_number->nb_xor(a, b);
- return PyBool_FromLong(
- ((PyBoolObject *)a)->ob_ival ^ ((PyBoolObject *)b)->ob_ival);
-}
-
-/* Doc string */
-
-PyDoc_STRVAR(bool_doc,
-"bool(x) -> bool\n\
-\n\
-Returns True when the argument x is true, False otherwise.\n\
-The builtins True and False are the only two instances of the class bool.\n\
-The class bool is a subclass of the class int, and cannot be subclassed.");
-
-/* Arithmetic methods -- only so we can override &, |, ^. */
-
-static PyNumberMethods bool_as_number = {
- 0, /* nb_add */
- 0, /* nb_subtract */
- 0, /* nb_multiply */
- 0, /* nb_divide */
- 0, /* nb_remainder */
- 0, /* nb_divmod */
- 0, /* nb_power */
- 0, /* nb_negative */
- 0, /* nb_positive */
- 0, /* nb_absolute */
- 0, /* nb_nonzero */
- 0, /* nb_invert */
- 0, /* nb_lshift */
- 0, /* nb_rshift */
- bool_and, /* nb_and */
- bool_xor, /* nb_xor */
- bool_or, /* nb_or */
- 0, /* nb_coerce */
- 0, /* nb_int */
- 0, /* nb_long */
- 0, /* nb_float */
- 0, /* nb_oct */
- 0, /* nb_hex */
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_divide */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- 0, /* nb_floor_divide */
- 0, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
-};
-
-/* The type object for bool. Note that this cannot be subclassed! */
-
-PyTypeObject PyBool_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "bool",
- sizeof(PyIntObject),
- 0,
- 0, /* tp_dealloc */
- (printfunc)bool_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)bool_repr, /* tp_repr */
- &bool_as_number, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)bool_repr, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
- bool_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &PyInt_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- bool_new, /* tp_new */
-};
-
-/* The objects representing bool values False and True */
-
-/* Named Zero for link-level compatibility */
-PyIntObject _Py_ZeroStruct = {
- PyObject_HEAD_INIT(&PyBool_Type)
- 0
-};
-
-PyIntObject _Py_TrueStruct = {
- PyObject_HEAD_INIT(&PyBool_Type)
- 1
-};
diff --git a/sys/src/cmd/python/Objects/bufferobject.c b/sys/src/cmd/python/Objects/bufferobject.c
deleted file mode 100644
index 5f3c7a9ee..000000000
--- a/sys/src/cmd/python/Objects/bufferobject.c
+++ /dev/null
@@ -1,706 +0,0 @@
-
-/* Buffer object implementation */
-
-#include "Python.h"
-
-
-typedef struct {
- PyObject_HEAD
- PyObject *b_base;
- void *b_ptr;
- Py_ssize_t b_size;
- Py_ssize_t b_offset;
- int b_readonly;
- long b_hash;
-} PyBufferObject;
-
-
-enum buffer_t {
- READ_BUFFER,
- WRITE_BUFFER,
- CHAR_BUFFER,
- ANY_BUFFER,
-};
-
-static int
-get_buf(PyBufferObject *self, void **ptr, Py_ssize_t *size,
- enum buffer_t buffer_type)
-{
- if (self->b_base == NULL) {
- assert (ptr != NULL);
- *ptr = self->b_ptr;
- *size = self->b_size;
- }
- else {
- Py_ssize_t count, offset;
- readbufferproc proc = 0;
- PyBufferProcs *bp = self->b_base->ob_type->tp_as_buffer;
- if ((*bp->bf_getsegcount)(self->b_base, NULL) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return 0;
- }
- if ((buffer_type == READ_BUFFER) ||
- ((buffer_type == ANY_BUFFER) && self->b_readonly))
- proc = bp->bf_getreadbuffer;
- else if ((buffer_type == WRITE_BUFFER) ||
- (buffer_type == ANY_BUFFER))
- proc = (readbufferproc)bp->bf_getwritebuffer;
- else if (buffer_type == CHAR_BUFFER) {
- if (!PyType_HasFeature(self->ob_type,
- Py_TPFLAGS_HAVE_GETCHARBUFFER)) {
- PyErr_SetString(PyExc_TypeError,
- "Py_TPFLAGS_HAVE_GETCHARBUFFER needed");
- return 0;
- }
- proc = (readbufferproc)bp->bf_getcharbuffer;
- }
- if (!proc) {
- char *buffer_type_name;
- switch (buffer_type) {
- case READ_BUFFER:
- buffer_type_name = "read";
- break;
- case WRITE_BUFFER:
- buffer_type_name = "write";
- break;
- case CHAR_BUFFER:
- buffer_type_name = "char";
- break;
- default:
- buffer_type_name = "no";
- break;
- }
- PyErr_Format(PyExc_TypeError,
- "%s buffer type not available",
- buffer_type_name);
- return 0;
- }
- if ((count = (*proc)(self->b_base, 0, ptr)) < 0)
- return 0;
- /* apply constraints to the start/end */
- if (self->b_offset > count)
- offset = count;
- else
- offset = self->b_offset;
- *(char **)ptr = *(char **)ptr + offset;
- if (self->b_size == Py_END_OF_BUFFER)
- *size = count;
- else
- *size = self->b_size;
- if (offset + *size > count)
- *size = count - offset;
- }
- return 1;
-}
-
-
-static PyObject *
-buffer_from_memory(PyObject *base, Py_ssize_t size, Py_ssize_t offset, void *ptr,
- int readonly)
-{
- PyBufferObject * b;
-
- if (size < 0 && size != Py_END_OF_BUFFER) {
- PyErr_SetString(PyExc_ValueError,
- "size must be zero or positive");
- return NULL;
- }
- if (offset < 0) {
- PyErr_SetString(PyExc_ValueError,
- "offset must be zero or positive");
- return NULL;
- }
-
- b = PyObject_NEW(PyBufferObject, &PyBuffer_Type);
- if ( b == NULL )
- return NULL;
-
- Py_XINCREF(base);
- b->b_base = base;
- b->b_ptr = ptr;
- b->b_size = size;
- b->b_offset = offset;
- b->b_readonly = readonly;
- b->b_hash = -1;
-
- return (PyObject *) b;
-}
-
-static PyObject *
-buffer_from_object(PyObject *base, Py_ssize_t size, Py_ssize_t offset, int readonly)
-{
- if (offset < 0) {
- PyErr_SetString(PyExc_ValueError,
- "offset must be zero or positive");
- return NULL;
- }
- if ( PyBuffer_Check(base) && (((PyBufferObject *)base)->b_base) ) {
- /* another buffer, refer to the base object */
- PyBufferObject *b = (PyBufferObject *)base;
- if (b->b_size != Py_END_OF_BUFFER) {
- Py_ssize_t base_size = b->b_size - offset;
- if (base_size < 0)
- base_size = 0;
- if (size == Py_END_OF_BUFFER || size > base_size)
- size = base_size;
- }
- offset += b->b_offset;
- base = b->b_base;
- }
- return buffer_from_memory(base, size, offset, NULL, readonly);
-}
-
-
-PyObject *
-PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
-{
- PyBufferProcs *pb = base->ob_type->tp_as_buffer;
-
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_SetString(PyExc_TypeError, "buffer object expected");
- return NULL;
- }
-
- return buffer_from_object(base, size, offset, 1);
-}
-
-PyObject *
-PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
-{
- PyBufferProcs *pb = base->ob_type->tp_as_buffer;
-
- if ( pb == NULL ||
- pb->bf_getwritebuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_SetString(PyExc_TypeError, "buffer object expected");
- return NULL;
- }
-
- return buffer_from_object(base, size, offset, 0);
-}
-
-PyObject *
-PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
-{
- return buffer_from_memory(NULL, size, 0, ptr, 1);
-}
-
-PyObject *
-PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
-{
- return buffer_from_memory(NULL, size, 0, ptr, 0);
-}
-
-PyObject *
-PyBuffer_New(Py_ssize_t size)
-{
- PyObject *o;
- PyBufferObject * b;
-
- if (size < 0) {
- PyErr_SetString(PyExc_ValueError,
- "size must be zero or positive");
- return NULL;
- }
- /* XXX: check for overflow in multiply */
- /* Inline PyObject_New */
- o = (PyObject *)PyObject_MALLOC(sizeof(*b) + size);
- if ( o == NULL )
- return PyErr_NoMemory();
- b = (PyBufferObject *) PyObject_INIT(o, &PyBuffer_Type);
-
- b->b_base = NULL;
- b->b_ptr = (void *)(b + 1);
- b->b_size = size;
- b->b_offset = 0;
- b->b_readonly = 0;
- b->b_hash = -1;
-
- return o;
-}
-
-/* Methods */
-
-static PyObject *
-buffer_new(PyTypeObject *type, PyObject *args, PyObject *kw)
-{
- PyObject *ob;
- Py_ssize_t offset = 0;
- Py_ssize_t size = Py_END_OF_BUFFER;
-
- if (!_PyArg_NoKeywords("buffer()", kw))
- return NULL;
-
- if (!PyArg_ParseTuple(args, "O|nn:buffer", &ob, &offset, &size))
- return NULL;
- return PyBuffer_FromObject(ob, offset, size);
-}
-
-PyDoc_STRVAR(buffer_doc,
-"buffer(object [, offset[, size]])\n\
-\n\
-Create a new buffer object which references the given object.\n\
-The buffer will reference a slice of the target object from the\n\
-start of the object (or at the specified offset). The slice will\n\
-extend to the end of the target object (or with the specified size).");
-
-
-static void
-buffer_dealloc(PyBufferObject *self)
-{
- Py_XDECREF(self->b_base);
- PyObject_DEL(self);
-}
-
-static int
-buffer_compare(PyBufferObject *self, PyBufferObject *other)
-{
- void *p1, *p2;
- Py_ssize_t len_self, len_other, min_len;
- int cmp;
-
- if (!get_buf(self, &p1, &len_self, ANY_BUFFER))
- return -1;
- if (!get_buf(other, &p2, &len_other, ANY_BUFFER))
- return -1;
- min_len = (len_self < len_other) ? len_self : len_other;
- if (min_len > 0) {
- cmp = memcmp(p1, p2, min_len);
- if (cmp != 0)
- return cmp < 0 ? -1 : 1;
- }
- return (len_self < len_other) ? -1 : (len_self > len_other) ? 1 : 0;
-}
-
-static PyObject *
-buffer_repr(PyBufferObject *self)
-{
- const char *status = self->b_readonly ? "read-only" : "read-write";
-
- if ( self->b_base == NULL )
- return PyString_FromFormat("<%s buffer ptr %p, size %zd at %p>",
- status,
- self->b_ptr,
- self->b_size,
- self);
- else
- return PyString_FromFormat(
- "<%s buffer for %p, size %zd, offset %zd at %p>",
- status,
- self->b_base,
- self->b_size,
- self->b_offset,
- self);
-}
-
-static long
-buffer_hash(PyBufferObject *self)
-{
- void *ptr;
- Py_ssize_t size;
- register Py_ssize_t len;
- register unsigned char *p;
- register long x;
-
- if ( self->b_hash != -1 )
- return self->b_hash;
-
- /* XXX potential bugs here, a readonly buffer does not imply that the
- * underlying memory is immutable. b_readonly is a necessary but not
- * sufficient condition for a buffer to be hashable. Perhaps it would
- * be better to only allow hashing if the underlying object is known to
- * be immutable (e.g. PyString_Check() is true). Another idea would
- * be to call tp_hash on the underlying object and see if it raises
- * an error. */
- if ( !self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError,
- "writable buffers are not hashable");
- return -1;
- }
-
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return -1;
- p = (unsigned char *) ptr;
- len = size;
- x = *p << 7;
- while (--len >= 0)
- x = (1000003*x) ^ *p++;
- x ^= size;
- if (x == -1)
- x = -2;
- self->b_hash = x;
- return x;
-}
-
-static PyObject *
-buffer_str(PyBufferObject *self)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- return PyString_FromStringAndSize((const char *)ptr, size);
-}
-
-/* Sequence methods */
-
-static Py_ssize_t
-buffer_length(PyBufferObject *self)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return -1;
- return size;
-}
-
-static PyObject *
-buffer_concat(PyBufferObject *self, PyObject *other)
-{
- PyBufferProcs *pb = other->ob_type->tp_as_buffer;
- void *ptr1, *ptr2;
- char *p;
- PyObject *ob;
- Py_ssize_t size, count;
-
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return NULL;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return NULL;
- }
-
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return NULL;
-
- /* optimize special case */
- if ( size == 0 )
- {
- Py_INCREF(other);
- return other;
- }
-
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return NULL;
-
- ob = PyString_FromStringAndSize(NULL, size + count);
- if ( ob == NULL )
- return NULL;
- p = PyString_AS_STRING(ob);
- memcpy(p, ptr1, size);
- memcpy(p + size, ptr2, count);
-
- /* there is an extra byte in the string object, so this is safe */
- p[size + count] = '\0';
-
- return ob;
-}
-
-static PyObject *
-buffer_repeat(PyBufferObject *self, Py_ssize_t count)
-{
- PyObject *ob;
- register char *p;
- void *ptr;
- Py_ssize_t size;
-
- if ( count < 0 )
- count = 0;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- ob = PyString_FromStringAndSize(NULL, size * count);
- if ( ob == NULL )
- return NULL;
-
- p = PyString_AS_STRING(ob);
- while ( count-- )
- {
- memcpy(p, ptr, size);
- p += size;
- }
-
- /* there is an extra byte in the string object, so this is safe */
- *p = '\0';
-
- return ob;
-}
-
-static PyObject *
-buffer_item(PyBufferObject *self, Py_ssize_t idx)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- if ( idx < 0 || idx >= size ) {
- PyErr_SetString(PyExc_IndexError, "buffer index out of range");
- return NULL;
- }
- return PyString_FromStringAndSize((char *)ptr + idx, 1);
-}
-
-static PyObject *
-buffer_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return NULL;
- if ( left < 0 )
- left = 0;
- if ( right < 0 )
- right = 0;
- if ( right > size )
- right = size;
- if ( right < left )
- right = left;
- return PyString_FromStringAndSize((char *)ptr + left,
- right - left);
-}
-
-static int
-buffer_ass_item(PyBufferObject *self, Py_ssize_t idx, PyObject *other)
-{
- PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
- Py_ssize_t count;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
-
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return -1;
-
- if (idx < 0 || idx >= size) {
- PyErr_SetString(PyExc_IndexError,
- "buffer assignment index out of range");
- return -1;
- }
-
- pb = other ? other->ob_type->tp_as_buffer : NULL;
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return -1;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
-
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
- if ( count != 1 ) {
- PyErr_SetString(PyExc_TypeError,
- "right operand must be a single byte");
- return -1;
- }
-
- ((char *)ptr1)[idx] = *(char *)ptr2;
- return 0;
-}
-
-static int
-buffer_ass_slice(PyBufferObject *self, Py_ssize_t left, Py_ssize_t right, PyObject *other)
-{
- PyBufferProcs *pb;
- void *ptr1, *ptr2;
- Py_ssize_t size;
- Py_ssize_t slice_len;
- Py_ssize_t count;
-
- if ( self->b_readonly ) {
- PyErr_SetString(PyExc_TypeError,
- "buffer is read-only");
- return -1;
- }
-
- pb = other ? other->ob_type->tp_as_buffer : NULL;
- if ( pb == NULL ||
- pb->bf_getreadbuffer == NULL ||
- pb->bf_getsegcount == NULL )
- {
- PyErr_BadArgument();
- return -1;
- }
- if ( (*pb->bf_getsegcount)(other, NULL) != 1 )
- {
- /* ### use a different exception type/message? */
- PyErr_SetString(PyExc_TypeError,
- "single-segment buffer object expected");
- return -1;
- }
- if (!get_buf(self, &ptr1, &size, ANY_BUFFER))
- return -1;
- if ( (count = (*pb->bf_getreadbuffer)(other, 0, &ptr2)) < 0 )
- return -1;
-
- if ( left < 0 )
- left = 0;
- else if ( left > size )
- left = size;
- if ( right < left )
- right = left;
- else if ( right > size )
- right = size;
- slice_len = right - left;
-
- if ( count != slice_len ) {
- PyErr_SetString(
- PyExc_TypeError,
- "right operand length must match slice length");
- return -1;
- }
-
- if ( slice_len )
- memcpy((char *)ptr1 + left, ptr2, slice_len);
-
- return 0;
-}
-
-/* Buffer methods */
-
-static Py_ssize_t
-buffer_getreadbuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
-{
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, pp, &size, READ_BUFFER))
- return -1;
- return size;
-}
-
-static Py_ssize_t
-buffer_getwritebuf(PyBufferObject *self, Py_ssize_t idx, void **pp)
-{
- Py_ssize_t size;
-
- if ( self->b_readonly )
- {
- PyErr_SetString(PyExc_TypeError, "buffer is read-only");
- return -1;
- }
-
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, pp, &size, WRITE_BUFFER))
- return -1;
- return size;
-}
-
-static Py_ssize_t
-buffer_getsegcount(PyBufferObject *self, Py_ssize_t *lenp)
-{
- void *ptr;
- Py_ssize_t size;
- if (!get_buf(self, &ptr, &size, ANY_BUFFER))
- return -1;
- if (lenp)
- *lenp = size;
- return 1;
-}
-
-static Py_ssize_t
-buffer_getcharbuf(PyBufferObject *self, Py_ssize_t idx, const char **pp)
-{
- void *ptr;
- Py_ssize_t size;
- if ( idx != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent buffer segment");
- return -1;
- }
- if (!get_buf(self, &ptr, &size, CHAR_BUFFER))
- return -1;
- *pp = (const char *)ptr;
- return size;
-}
-
-static PySequenceMethods buffer_as_sequence = {
- (lenfunc)buffer_length, /*sq_length*/
- (binaryfunc)buffer_concat, /*sq_concat*/
- (ssizeargfunc)buffer_repeat, /*sq_repeat*/
- (ssizeargfunc)buffer_item, /*sq_item*/
- (ssizessizeargfunc)buffer_slice, /*sq_slice*/
- (ssizeobjargproc)buffer_ass_item, /*sq_ass_item*/
- (ssizessizeobjargproc)buffer_ass_slice, /*sq_ass_slice*/
-};
-
-static PyBufferProcs buffer_as_buffer = {
- (readbufferproc)buffer_getreadbuf,
- (writebufferproc)buffer_getwritebuf,
- (segcountproc)buffer_getsegcount,
- (charbufferproc)buffer_getcharbuf,
-};
-
-PyTypeObject PyBuffer_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "buffer",
- sizeof(PyBufferObject),
- 0,
- (destructor)buffer_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)buffer_compare, /* tp_compare */
- (reprfunc)buffer_repr, /* tp_repr */
- 0, /* tp_as_number */
- &buffer_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)buffer_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)buffer_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- &buffer_as_buffer, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GETCHARBUFFER, /* tp_flags */
- buffer_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- buffer_new, /* tp_new */
-};
diff --git a/sys/src/cmd/python/Objects/cellobject.c b/sys/src/cmd/python/Objects/cellobject.c
deleted file mode 100644
index 65a29aaca..000000000
--- a/sys/src/cmd/python/Objects/cellobject.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/* Cell object implementation */
-
-#include "Python.h"
-
-PyObject *
-PyCell_New(PyObject *obj)
-{
- PyCellObject *op;
-
- op = (PyCellObject *)PyObject_GC_New(PyCellObject, &PyCell_Type);
- if (op == NULL)
- return NULL;
- op->ob_ref = obj;
- Py_XINCREF(obj);
-
- _PyObject_GC_TRACK(op);
- return (PyObject *)op;
-}
-
-PyObject *
-PyCell_Get(PyObject *op)
-{
- if (!PyCell_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- Py_XINCREF(((PyCellObject*)op)->ob_ref);
- return PyCell_GET(op);
-}
-
-int
-PyCell_Set(PyObject *op, PyObject *obj)
-{
- if (!PyCell_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- Py_XDECREF(((PyCellObject*)op)->ob_ref);
- Py_XINCREF(obj);
- PyCell_SET(op, obj);
- return 0;
-}
-
-static void
-cell_dealloc(PyCellObject *op)
-{
- _PyObject_GC_UNTRACK(op);
- Py_XDECREF(op->ob_ref);
- PyObject_GC_Del(op);
-}
-
-static int
-cell_compare(PyCellObject *a, PyCellObject *b)
-{
- if (a->ob_ref == NULL) {
- if (b->ob_ref == NULL)
- return 0;
- return -1;
- } else if (b->ob_ref == NULL)
- return 1;
- return PyObject_Compare(a->ob_ref, b->ob_ref);
-}
-
-static PyObject *
-cell_repr(PyCellObject *op)
-{
- if (op->ob_ref == NULL)
- return PyString_FromFormat("<cell at %p: empty>", op);
-
- return PyString_FromFormat("<cell at %p: %.80s object at %p>",
- op, op->ob_ref->ob_type->tp_name,
- op->ob_ref);
-}
-
-static int
-cell_traverse(PyCellObject *op, visitproc visit, void *arg)
-{
- Py_VISIT(op->ob_ref);
- return 0;
-}
-
-static int
-cell_clear(PyCellObject *op)
-{
- Py_CLEAR(op->ob_ref);
- return 0;
-}
-
-static PyObject *
-cell_get_contents(PyCellObject *op, void *closure)
-{
- Py_XINCREF(op->ob_ref);
- return op->ob_ref;
-}
-
-static PyGetSetDef cell_getsetlist[] = {
- {"cell_contents", (getter)cell_get_contents, NULL},
- {NULL} /* sentinel */
-};
-
-PyTypeObject PyCell_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "cell",
- sizeof(PyCellObject),
- 0,
- (destructor)cell_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)cell_compare, /* tp_compare */
- (reprfunc)cell_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)cell_traverse, /* tp_traverse */
- (inquiry)cell_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- cell_getsetlist, /* tp_getset */
-};
diff --git a/sys/src/cmd/python/Objects/classobject.c b/sys/src/cmd/python/Objects/classobject.c
deleted file mode 100644
index 8560b6842..000000000
--- a/sys/src/cmd/python/Objects/classobject.c
+++ /dev/null
@@ -1,2580 +0,0 @@
-
-/* Class object implementation */
-
-#include "Python.h"
-#include "structmember.h"
-
-#define TP_DESCR_GET(t) \
- (PyType_HasFeature(t, Py_TPFLAGS_HAVE_CLASS) ? (t)->tp_descr_get : NULL)
-
-
-/* Forward */
-static PyObject *class_lookup(PyClassObject *, PyObject *,
- PyClassObject **);
-static PyObject *instance_getattr1(PyInstanceObject *, PyObject *);
-static PyObject *instance_getattr2(PyInstanceObject *, PyObject *);
-
-static PyObject *getattrstr, *setattrstr, *delattrstr;
-
-
-PyObject *
-PyClass_New(PyObject *bases, PyObject *dict, PyObject *name)
- /* bases is NULL or tuple of classobjects! */
-{
- PyClassObject *op, *dummy;
- static PyObject *docstr, *modstr, *namestr;
- if (docstr == NULL) {
- docstr= PyString_InternFromString("__doc__");
- if (docstr == NULL)
- return NULL;
- }
- if (modstr == NULL) {
- modstr= PyString_InternFromString("__module__");
- if (modstr == NULL)
- return NULL;
- }
- if (namestr == NULL) {
- namestr= PyString_InternFromString("__name__");
- if (namestr == NULL)
- return NULL;
- }
- if (name == NULL || !PyString_Check(name)) {
- PyErr_SetString(PyExc_TypeError,
- "PyClass_New: name must be a string");
- return NULL;
- }
- if (dict == NULL || !PyDict_Check(dict)) {
- PyErr_SetString(PyExc_TypeError,
- "PyClass_New: dict must be a dictionary");
- return NULL;
- }
- if (PyDict_GetItem(dict, docstr) == NULL) {
- if (PyDict_SetItem(dict, docstr, Py_None) < 0)
- return NULL;
- }
- if (PyDict_GetItem(dict, modstr) == NULL) {
- PyObject *globals = PyEval_GetGlobals();
- if (globals != NULL) {
- PyObject *modname = PyDict_GetItem(globals, namestr);
- if (modname != NULL) {
- if (PyDict_SetItem(dict, modstr, modname) < 0)
- return NULL;
- }
- }
- }
- if (bases == NULL) {
- bases = PyTuple_New(0);
- if (bases == NULL)
- return NULL;
- }
- else {
- Py_ssize_t i, n;
- PyObject *base;
- if (!PyTuple_Check(bases)) {
- PyErr_SetString(PyExc_TypeError,
- "PyClass_New: bases must be a tuple");
- return NULL;
- }
- n = PyTuple_Size(bases);
- for (i = 0; i < n; i++) {
- base = PyTuple_GET_ITEM(bases, i);
- if (!PyClass_Check(base)) {
- if (PyCallable_Check(
- (PyObject *) base->ob_type))
- return PyObject_CallFunctionObjArgs(
- (PyObject *) base->ob_type,
- name, bases, dict, NULL);
- PyErr_SetString(PyExc_TypeError,
- "PyClass_New: base must be a class");
- return NULL;
- }
- }
- Py_INCREF(bases);
- }
-
- if (getattrstr == NULL) {
- getattrstr = PyString_InternFromString("__getattr__");
- if (getattrstr == NULL)
- goto alloc_error;
- setattrstr = PyString_InternFromString("__setattr__");
- if (setattrstr == NULL)
- goto alloc_error;
- delattrstr = PyString_InternFromString("__delattr__");
- if (delattrstr == NULL)
- goto alloc_error;
- }
-
- op = PyObject_GC_New(PyClassObject, &PyClass_Type);
- if (op == NULL) {
-alloc_error:
- Py_DECREF(bases);
- return NULL;
- }
- op->cl_bases = bases;
- Py_INCREF(dict);
- op->cl_dict = dict;
- Py_XINCREF(name);
- op->cl_name = name;
-
- op->cl_getattr = class_lookup(op, getattrstr, &dummy);
- op->cl_setattr = class_lookup(op, setattrstr, &dummy);
- op->cl_delattr = class_lookup(op, delattrstr, &dummy);
- Py_XINCREF(op->cl_getattr);
- Py_XINCREF(op->cl_setattr);
- Py_XINCREF(op->cl_delattr);
- _PyObject_GC_TRACK(op);
- return (PyObject *) op;
-}
-
-PyObject *
-PyMethod_Function(PyObject *im)
-{
- if (!PyMethod_Check(im)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyMethodObject *)im)->im_func;
-}
-
-PyObject *
-PyMethod_Self(PyObject *im)
-{
- if (!PyMethod_Check(im)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyMethodObject *)im)->im_self;
-}
-
-PyObject *
-PyMethod_Class(PyObject *im)
-{
- if (!PyMethod_Check(im)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyMethodObject *)im)->im_class;
-}
-
-PyDoc_STRVAR(class_doc,
-"classobj(name, bases, dict)\n\
-\n\
-Create a class object. The name must be a string; the second argument\n\
-a tuple of classes, and the third a dictionary.");
-
-static PyObject *
-class_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *name, *bases, *dict;
- static char *kwlist[] = {"name", "bases", "dict", 0};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", kwlist,
- &name, &bases, &dict))
- return NULL;
- return PyClass_New(bases, dict, name);
-}
-
-/* Class methods */
-
-static void
-class_dealloc(PyClassObject *op)
-{
- _PyObject_GC_UNTRACK(op);
- Py_DECREF(op->cl_bases);
- Py_DECREF(op->cl_dict);
- Py_XDECREF(op->cl_name);
- Py_XDECREF(op->cl_getattr);
- Py_XDECREF(op->cl_setattr);
- Py_XDECREF(op->cl_delattr);
- PyObject_GC_Del(op);
-}
-
-static PyObject *
-class_lookup(PyClassObject *cp, PyObject *name, PyClassObject **pclass)
-{
- Py_ssize_t i, n;
- PyObject *value = PyDict_GetItem(cp->cl_dict, name);
- if (value != NULL) {
- *pclass = cp;
- return value;
- }
- n = PyTuple_Size(cp->cl_bases);
- for (i = 0; i < n; i++) {
- /* XXX What if one of the bases is not a class? */
- PyObject *v = class_lookup(
- (PyClassObject *)
- PyTuple_GetItem(cp->cl_bases, i), name, pclass);
- if (v != NULL)
- return v;
- }
- return NULL;
-}
-
-static PyObject *
-class_getattr(register PyClassObject *op, PyObject *name)
-{
- register PyObject *v;
- register char *sname = PyString_AsString(name);
- PyClassObject *klass;
- descrgetfunc f;
-
- if (sname[0] == '_' && sname[1] == '_') {
- if (strcmp(sname, "__dict__") == 0) {
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "class.__dict__ not accessible in restricted mode");
- return NULL;
- }
- Py_INCREF(op->cl_dict);
- return op->cl_dict;
- }
- if (strcmp(sname, "__bases__") == 0) {
- Py_INCREF(op->cl_bases);
- return op->cl_bases;
- }
- if (strcmp(sname, "__name__") == 0) {
- if (op->cl_name == NULL)
- v = Py_None;
- else
- v = op->cl_name;
- Py_INCREF(v);
- return v;
- }
- }
- v = class_lookup(op, name, &klass);
- if (v == NULL) {
- PyErr_Format(PyExc_AttributeError,
- "class %.50s has no attribute '%.400s'",
- PyString_AS_STRING(op->cl_name), sname);
- return NULL;
- }
- f = TP_DESCR_GET(v->ob_type);
- if (f == NULL)
- Py_INCREF(v);
- else
- v = f(v, (PyObject *)NULL, (PyObject *)op);
- return v;
-}
-
-static void
-set_slot(PyObject **slot, PyObject *v)
-{
- PyObject *temp = *slot;
- Py_XINCREF(v);
- *slot = v;
- Py_XDECREF(temp);
-}
-
-static void
-set_attr_slots(PyClassObject *c)
-{
- PyClassObject *dummy;
-
- set_slot(&c->cl_getattr, class_lookup(c, getattrstr, &dummy));
- set_slot(&c->cl_setattr, class_lookup(c, setattrstr, &dummy));
- set_slot(&c->cl_delattr, class_lookup(c, delattrstr, &dummy));
-}
-
-static char *
-set_dict(PyClassObject *c, PyObject *v)
-{
- if (v == NULL || !PyDict_Check(v))
- return "__dict__ must be a dictionary object";
- set_slot(&c->cl_dict, v);
- set_attr_slots(c);
- return "";
-}
-
-static char *
-set_bases(PyClassObject *c, PyObject *v)
-{
- Py_ssize_t i, n;
-
- if (v == NULL || !PyTuple_Check(v))
- return "__bases__ must be a tuple object";
- n = PyTuple_Size(v);
- for (i = 0; i < n; i++) {
- PyObject *x = PyTuple_GET_ITEM(v, i);
- if (!PyClass_Check(x))
- return "__bases__ items must be classes";
- if (PyClass_IsSubclass(x, (PyObject *)c))
- return "a __bases__ item causes an inheritance cycle";
- }
- set_slot(&c->cl_bases, v);
- set_attr_slots(c);
- return "";
-}
-
-static char *
-set_name(PyClassObject *c, PyObject *v)
-{
- if (v == NULL || !PyString_Check(v))
- return "__name__ must be a string object";
- if (strlen(PyString_AS_STRING(v)) != (size_t)PyString_GET_SIZE(v))
- return "__name__ must not contain null bytes";
- set_slot(&c->cl_name, v);
- return "";
-}
-
-static int
-class_setattr(PyClassObject *op, PyObject *name, PyObject *v)
-{
- char *sname;
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "classes are read-only in restricted mode");
- return -1;
- }
- sname = PyString_AsString(name);
- if (sname[0] == '_' && sname[1] == '_') {
- Py_ssize_t n = PyString_Size(name);
- if (sname[n-1] == '_' && sname[n-2] == '_') {
- char *err = NULL;
- if (strcmp(sname, "__dict__") == 0)
- err = set_dict(op, v);
- else if (strcmp(sname, "__bases__") == 0)
- err = set_bases(op, v);
- else if (strcmp(sname, "__name__") == 0)
- err = set_name(op, v);
- else if (strcmp(sname, "__getattr__") == 0)
- set_slot(&op->cl_getattr, v);
- else if (strcmp(sname, "__setattr__") == 0)
- set_slot(&op->cl_setattr, v);
- else if (strcmp(sname, "__delattr__") == 0)
- set_slot(&op->cl_delattr, v);
- /* For the last three, we fall through to update the
- dictionary as well. */
- if (err != NULL) {
- if (*err == '\0')
- return 0;
- PyErr_SetString(PyExc_TypeError, err);
- return -1;
- }
- }
- }
- if (v == NULL) {
- int rv = PyDict_DelItem(op->cl_dict, name);
- if (rv < 0)
- PyErr_Format(PyExc_AttributeError,
- "class %.50s has no attribute '%.400s'",
- PyString_AS_STRING(op->cl_name), sname);
- return rv;
- }
- else
- return PyDict_SetItem(op->cl_dict, name, v);
-}
-
-static PyObject *
-class_repr(PyClassObject *op)
-{
- PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__");
- char *name;
- if (op->cl_name == NULL || !PyString_Check(op->cl_name))
- name = "?";
- else
- name = PyString_AsString(op->cl_name);
- if (mod == NULL || !PyString_Check(mod))
- return PyString_FromFormat("<class ?.%s at %p>", name, op);
- else
- return PyString_FromFormat("<class %s.%s at %p>",
- PyString_AsString(mod),
- name, op);
-}
-
-static PyObject *
-class_str(PyClassObject *op)
-{
- PyObject *mod = PyDict_GetItemString(op->cl_dict, "__module__");
- PyObject *name = op->cl_name;
- PyObject *res;
- Py_ssize_t m, n;
-
- if (name == NULL || !PyString_Check(name))
- return class_repr(op);
- if (mod == NULL || !PyString_Check(mod)) {
- Py_INCREF(name);
- return name;
- }
- m = PyString_GET_SIZE(mod);
- n = PyString_GET_SIZE(name);
- res = PyString_FromStringAndSize((char *)NULL, m+1+n);
- if (res != NULL) {
- char *s = PyString_AS_STRING(res);
- memcpy(s, PyString_AS_STRING(mod), m);
- s += m;
- *s++ = '.';
- memcpy(s, PyString_AS_STRING(name), n);
- }
- return res;
-}
-
-static int
-class_traverse(PyClassObject *o, visitproc visit, void *arg)
-{
- Py_VISIT(o->cl_bases);
- Py_VISIT(o->cl_dict);
- Py_VISIT(o->cl_name);
- Py_VISIT(o->cl_getattr);
- Py_VISIT(o->cl_setattr);
- Py_VISIT(o->cl_delattr);
- return 0;
-}
-
-PyTypeObject PyClass_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "classobj",
- sizeof(PyClassObject),
- 0,
- (destructor)class_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)class_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- PyInstance_New, /* tp_call */
- (reprfunc)class_str, /* tp_str */
- (getattrofunc)class_getattr, /* tp_getattro */
- (setattrofunc)class_setattr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- class_doc, /* tp_doc */
- (traverseproc)class_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- class_new, /* tp_new */
-};
-
-int
-PyClass_IsSubclass(PyObject *klass, PyObject *base)
-{
- Py_ssize_t i, n;
- PyClassObject *cp;
- if (klass == base)
- return 1;
- if (PyTuple_Check(base)) {
- n = PyTuple_GET_SIZE(base);
- for (i = 0; i < n; i++) {
- if (PyClass_IsSubclass(klass, PyTuple_GET_ITEM(base, i)))
- return 1;
- }
- return 0;
- }
- if (klass == NULL || !PyClass_Check(klass))
- return 0;
- cp = (PyClassObject *)klass;
- n = PyTuple_Size(cp->cl_bases);
- for (i = 0; i < n; i++) {
- if (PyClass_IsSubclass(PyTuple_GetItem(cp->cl_bases, i), base))
- return 1;
- }
- return 0;
-}
-
-
-/* Instance objects */
-
-PyObject *
-PyInstance_NewRaw(PyObject *klass, PyObject *dict)
-{
- PyInstanceObject *inst;
-
- if (!PyClass_Check(klass)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- if (dict == NULL) {
- dict = PyDict_New();
- if (dict == NULL)
- return NULL;
- }
- else {
- if (!PyDict_Check(dict)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- Py_INCREF(dict);
- }
- inst = PyObject_GC_New(PyInstanceObject, &PyInstance_Type);
- if (inst == NULL) {
- Py_DECREF(dict);
- return NULL;
- }
- inst->in_weakreflist = NULL;
- Py_INCREF(klass);
- inst->in_class = (PyClassObject *)klass;
- inst->in_dict = dict;
- _PyObject_GC_TRACK(inst);
- return (PyObject *)inst;
-}
-
-PyObject *
-PyInstance_New(PyObject *klass, PyObject *arg, PyObject *kw)
-{
- register PyInstanceObject *inst;
- PyObject *init;
- static PyObject *initstr;
-
- if (initstr == NULL) {
- initstr = PyString_InternFromString("__init__");
- if (initstr == NULL)
- return NULL;
- }
- inst = (PyInstanceObject *) PyInstance_NewRaw(klass, NULL);
- if (inst == NULL)
- return NULL;
- init = instance_getattr2(inst, initstr);
- if (init == NULL) {
- if (PyErr_Occurred()) {
- Py_DECREF(inst);
- return NULL;
- }
- if ((arg != NULL && (!PyTuple_Check(arg) ||
- PyTuple_Size(arg) != 0))
- || (kw != NULL && (!PyDict_Check(kw) ||
- PyDict_Size(kw) != 0))) {
- PyErr_SetString(PyExc_TypeError,
- "this constructor takes no arguments");
- Py_DECREF(inst);
- inst = NULL;
- }
- }
- else {
- PyObject *res = PyEval_CallObjectWithKeywords(init, arg, kw);
- Py_DECREF(init);
- if (res == NULL) {
- Py_DECREF(inst);
- inst = NULL;
- }
- else {
- if (res != Py_None) {
- PyErr_SetString(PyExc_TypeError,
- "__init__() should return None");
- Py_DECREF(inst);
- inst = NULL;
- }
- Py_DECREF(res);
- }
- }
- return (PyObject *)inst;
-}
-
-/* Instance methods */
-
-PyDoc_STRVAR(instance_doc,
-"instance(class[, dict])\n\
-\n\
-Create an instance without calling its __init__() method.\n\
-The class must be a classic class.\n\
-If present, dict must be a dictionary or None.");
-
-static PyObject *
-instance_new(PyTypeObject* type, PyObject* args, PyObject *kw)
-{
- PyObject *klass;
- PyObject *dict = Py_None;
-
- if (!PyArg_ParseTuple(args, "O!|O:instance",
- &PyClass_Type, &klass, &dict))
- return NULL;
-
- if (dict == Py_None)
- dict = NULL;
- else if (!PyDict_Check(dict)) {
- PyErr_SetString(PyExc_TypeError,
- "instance() second arg must be dictionary or None");
- return NULL;
- }
- return PyInstance_NewRaw(klass, dict);
-}
-
-
-static void
-instance_dealloc(register PyInstanceObject *inst)
-{
- PyObject *error_type, *error_value, *error_traceback;
- PyObject *del;
- static PyObject *delstr;
-
- _PyObject_GC_UNTRACK(inst);
- if (inst->in_weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) inst);
-
- /* Temporarily resurrect the object. */
- assert(inst->ob_type == &PyInstance_Type);
- assert(inst->ob_refcnt == 0);
- inst->ob_refcnt = 1;
-
- /* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
- /* Execute __del__ method, if any. */
- if (delstr == NULL) {
- delstr = PyString_InternFromString("__del__");
- if (delstr == NULL)
- PyErr_WriteUnraisable((PyObject*)inst);
- }
- if (delstr && (del = instance_getattr2(inst, delstr)) != NULL) {
- PyObject *res = PyEval_CallObject(del, (PyObject *)NULL);
- if (res == NULL)
- PyErr_WriteUnraisable(del);
- else
- Py_DECREF(res);
- Py_DECREF(del);
- }
- /* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
-
- /* Undo the temporary resurrection; can't use DECREF here, it would
- * cause a recursive call.
- */
- assert(inst->ob_refcnt > 0);
- if (--inst->ob_refcnt == 0) {
- Py_DECREF(inst->in_class);
- Py_XDECREF(inst->in_dict);
- PyObject_GC_Del(inst);
- }
- else {
- Py_ssize_t refcnt = inst->ob_refcnt;
- /* __del__ resurrected it! Make it look like the original
- * Py_DECREF never happened.
- */
- _Py_NewReference((PyObject *)inst);
- inst->ob_refcnt = refcnt;
- _PyObject_GC_TRACK(inst);
- /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
- * we need to undo that. */
- _Py_DEC_REFTOTAL;
- /* If Py_TRACE_REFS, _Py_NewReference re-added self to the
- * object chain, so no more to do there.
- * If COUNT_ALLOCS, the original decref bumped tp_frees, and
- * _Py_NewReference bumped tp_allocs: both of those need to be
- * undone.
- */
-#ifdef COUNT_ALLOCS
- --inst->ob_type->tp_frees;
- --inst->ob_type->tp_allocs;
-#endif
- }
-}
-
-static PyObject *
-instance_getattr1(register PyInstanceObject *inst, PyObject *name)
-{
- register PyObject *v;
- register char *sname = PyString_AsString(name);
- if (sname[0] == '_' && sname[1] == '_') {
- if (strcmp(sname, "__dict__") == 0) {
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "instance.__dict__ not accessible in restricted mode");
- return NULL;
- }
- Py_INCREF(inst->in_dict);
- return inst->in_dict;
- }
- if (strcmp(sname, "__class__") == 0) {
- Py_INCREF(inst->in_class);
- return (PyObject *)inst->in_class;
- }
- }
- v = instance_getattr2(inst, name);
- if (v == NULL && !PyErr_Occurred()) {
- PyErr_Format(PyExc_AttributeError,
- "%.50s instance has no attribute '%.400s'",
- PyString_AS_STRING(inst->in_class->cl_name), sname);
- }
- return v;
-}
-
-static PyObject *
-instance_getattr2(register PyInstanceObject *inst, PyObject *name)
-{
- register PyObject *v;
- PyClassObject *klass;
- descrgetfunc f;
-
- v = PyDict_GetItem(inst->in_dict, name);
- if (v != NULL) {
- Py_INCREF(v);
- return v;
- }
- v = class_lookup(inst->in_class, name, &klass);
- if (v != NULL) {
- Py_INCREF(v);
- f = TP_DESCR_GET(v->ob_type);
- if (f != NULL) {
- PyObject *w = f(v, (PyObject *)inst,
- (PyObject *)(inst->in_class));
- Py_DECREF(v);
- v = w;
- }
- }
- return v;
-}
-
-static PyObject *
-instance_getattr(register PyInstanceObject *inst, PyObject *name)
-{
- register PyObject *func, *res;
- res = instance_getattr1(inst, name);
- if (res == NULL && (func = inst->in_class->cl_getattr) != NULL) {
- PyObject *args;
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- args = PyTuple_Pack(2, inst, name);
- if (args == NULL)
- return NULL;
- res = PyEval_CallObject(func, args);
- Py_DECREF(args);
- }
- return res;
-}
-
-/* See classobject.h comments: this only does dict lookups, and is always
- * safe to call.
- */
-PyObject *
-_PyInstance_Lookup(PyObject *pinst, PyObject *name)
-{
- PyObject *v;
- PyClassObject *klass;
- PyInstanceObject *inst; /* pinst cast to the right type */
-
- assert(PyInstance_Check(pinst));
- inst = (PyInstanceObject *)pinst;
-
- assert(PyString_Check(name));
-
- v = PyDict_GetItem(inst->in_dict, name);
- if (v == NULL)
- v = class_lookup(inst->in_class, name, &klass);
- return v;
-}
-
-static int
-instance_setattr1(PyInstanceObject *inst, PyObject *name, PyObject *v)
-{
- if (v == NULL) {
- int rv = PyDict_DelItem(inst->in_dict, name);
- if (rv < 0)
- PyErr_Format(PyExc_AttributeError,
- "%.50s instance has no attribute '%.400s'",
- PyString_AS_STRING(inst->in_class->cl_name),
- PyString_AS_STRING(name));
- return rv;
- }
- else
- return PyDict_SetItem(inst->in_dict, name, v);
-}
-
-static int
-instance_setattr(PyInstanceObject *inst, PyObject *name, PyObject *v)
-{
- PyObject *func, *args, *res, *tmp;
- char *sname = PyString_AsString(name);
- if (sname[0] == '_' && sname[1] == '_') {
- Py_ssize_t n = PyString_Size(name);
- if (sname[n-1] == '_' && sname[n-2] == '_') {
- if (strcmp(sname, "__dict__") == 0) {
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "__dict__ not accessible in restricted mode");
- return -1;
- }
- if (v == NULL || !PyDict_Check(v)) {
- PyErr_SetString(PyExc_TypeError,
- "__dict__ must be set to a dictionary");
- return -1;
- }
- tmp = inst->in_dict;
- Py_INCREF(v);
- inst->in_dict = v;
- Py_DECREF(tmp);
- return 0;
- }
- if (strcmp(sname, "__class__") == 0) {
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "__class__ not accessible in restricted mode");
- return -1;
- }
- if (v == NULL || !PyClass_Check(v)) {
- PyErr_SetString(PyExc_TypeError,
- "__class__ must be set to a class");
- return -1;
- }
- tmp = (PyObject *)(inst->in_class);
- Py_INCREF(v);
- inst->in_class = (PyClassObject *)v;
- Py_DECREF(tmp);
- return 0;
- }
- }
- }
- if (v == NULL)
- func = inst->in_class->cl_delattr;
- else
- func = inst->in_class->cl_setattr;
- if (func == NULL)
- return instance_setattr1(inst, name, v);
- if (v == NULL)
- args = PyTuple_Pack(2, inst, name);
- else
- args = PyTuple_Pack(3, inst, name, v);
- if (args == NULL)
- return -1;
- res = PyEval_CallObject(func, args);
- Py_DECREF(args);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static PyObject *
-instance_repr(PyInstanceObject *inst)
-{
- PyObject *func;
- PyObject *res;
- static PyObject *reprstr;
-
- if (reprstr == NULL) {
- reprstr = PyString_InternFromString("__repr__");
- if (reprstr == NULL)
- return NULL;
- }
- func = instance_getattr(inst, reprstr);
- if (func == NULL) {
- PyObject *classname, *mod;
- char *cname;
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- classname = inst->in_class->cl_name;
- mod = PyDict_GetItemString(inst->in_class->cl_dict,
- "__module__");
- if (classname != NULL && PyString_Check(classname))
- cname = PyString_AsString(classname);
- else
- cname = "?";
- if (mod == NULL || !PyString_Check(mod))
- return PyString_FromFormat("<?.%s instance at %p>",
- cname, inst);
- else
- return PyString_FromFormat("<%s.%s instance at %p>",
- PyString_AsString(mod),
- cname, inst);
- }
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- return res;
-}
-
-static PyObject *
-instance_str(PyInstanceObject *inst)
-{
- PyObject *func;
- PyObject *res;
- static PyObject *strstr;
-
- if (strstr == NULL) {
- strstr = PyString_InternFromString("__str__");
- if (strstr == NULL)
- return NULL;
- }
- func = instance_getattr(inst, strstr);
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- return instance_repr(inst);
- }
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- return res;
-}
-
-static long
-instance_hash(PyInstanceObject *inst)
-{
- PyObject *func;
- PyObject *res;
- long outcome;
- static PyObject *hashstr, *eqstr, *cmpstr;
-
- if (hashstr == NULL) {
- hashstr = PyString_InternFromString("__hash__");
- if (hashstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, hashstr);
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- /* If there is no __eq__ and no __cmp__ method, we hash on the
- address. If an __eq__ or __cmp__ method exists, there must
- be a __hash__. */
- if (eqstr == NULL) {
- eqstr = PyString_InternFromString("__eq__");
- if (eqstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, eqstr);
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- if (cmpstr == NULL) {
- cmpstr = PyString_InternFromString("__cmp__");
- if (cmpstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, cmpstr);
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(
- PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- return _Py_HashPointer(inst);
- }
- }
- Py_XDECREF(func);
- PyErr_SetString(PyExc_TypeError, "unhashable instance");
- return -1;
- }
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- if (res == NULL)
- return -1;
- if (PyInt_Check(res) || PyLong_Check(res))
- /* This already converts a -1 result to -2. */
- outcome = res->ob_type->tp_hash(res);
- else {
- PyErr_SetString(PyExc_TypeError,
- "__hash__() should return an int");
- outcome = -1;
- }
- Py_DECREF(res);
- return outcome;
-}
-
-static int
-instance_traverse(PyInstanceObject *o, visitproc visit, void *arg)
-{
- Py_VISIT(o->in_class);
- Py_VISIT(o->in_dict);
- return 0;
-}
-
-static PyObject *getitemstr, *setitemstr, *delitemstr, *lenstr;
-static PyObject *iterstr, *nextstr;
-
-static Py_ssize_t
-instance_length(PyInstanceObject *inst)
-{
- PyObject *func;
- PyObject *res;
- Py_ssize_t outcome;
-
- if (lenstr == NULL) {
- lenstr = PyString_InternFromString("__len__");
- if (lenstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, lenstr);
- if (func == NULL)
- return -1;
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- if (res == NULL)
- return -1;
- if (PyInt_Check(res)) {
- outcome = PyInt_AsSsize_t(res);
- if (outcome == -1 && PyErr_Occurred()) {
- Py_DECREF(res);
- return -1;
- }
-#if SIZEOF_SIZE_T < SIZEOF_INT
- /* Overflow check -- range of PyInt is more than C int */
- if (outcome != (int)outcome) {
- PyErr_SetString(PyExc_OverflowError,
- "__len__() should return 0 <= outcome < 2**31");
- outcome = -1;
- }
- else
-#endif
- if (outcome < 0) {
- PyErr_SetString(PyExc_ValueError,
- "__len__() should return >= 0");
- outcome = -1;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "__len__() should return an int");
- outcome = -1;
- }
- Py_DECREF(res);
- return outcome;
-}
-
-static PyObject *
-instance_subscript(PyInstanceObject *inst, PyObject *key)
-{
- PyObject *func;
- PyObject *arg;
- PyObject *res;
-
- if (getitemstr == NULL) {
- getitemstr = PyString_InternFromString("__getitem__");
- if (getitemstr == NULL)
- return NULL;
- }
- func = instance_getattr(inst, getitemstr);
- if (func == NULL)
- return NULL;
- arg = PyTuple_Pack(1, key);
- if (arg == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- res = PyEval_CallObject(func, arg);
- Py_DECREF(func);
- Py_DECREF(arg);
- return res;
-}
-
-static int
-instance_ass_subscript(PyInstanceObject *inst, PyObject *key, PyObject *value)
-{
- PyObject *func;
- PyObject *arg;
- PyObject *res;
-
- if (value == NULL) {
- if (delitemstr == NULL) {
- delitemstr = PyString_InternFromString("__delitem__");
- if (delitemstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, delitemstr);
- }
- else {
- if (setitemstr == NULL) {
- setitemstr = PyString_InternFromString("__setitem__");
- if (setitemstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, setitemstr);
- }
- if (func == NULL)
- return -1;
- if (value == NULL)
- arg = PyTuple_Pack(1, key);
- else
- arg = PyTuple_Pack(2, key, value);
- if (arg == NULL) {
- Py_DECREF(func);
- return -1;
- }
- res = PyEval_CallObject(func, arg);
- Py_DECREF(func);
- Py_DECREF(arg);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static PyMappingMethods instance_as_mapping = {
- (lenfunc)instance_length, /* mp_length */
- (binaryfunc)instance_subscript, /* mp_subscript */
- (objobjargproc)instance_ass_subscript, /* mp_ass_subscript */
-};
-
-static PyObject *
-instance_item(PyInstanceObject *inst, Py_ssize_t i)
-{
- PyObject *func, *res;
-
- if (getitemstr == NULL) {
- getitemstr = PyString_InternFromString("__getitem__");
- if (getitemstr == NULL)
- return NULL;
- }
- func = instance_getattr(inst, getitemstr);
- if (func == NULL)
- return NULL;
- res = PyObject_CallFunction(func, "n", i);
- Py_DECREF(func);
- return res;
-}
-
-static PyObject *
-instance_slice(PyInstanceObject *inst, Py_ssize_t i, Py_ssize_t j)
-{
- PyObject *func, *arg, *res;
- static PyObject *getslicestr;
-
- if (getslicestr == NULL) {
- getslicestr = PyString_InternFromString("__getslice__");
- if (getslicestr == NULL)
- return NULL;
- }
- func = instance_getattr(inst, getslicestr);
-
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
-
- if (getitemstr == NULL) {
- getitemstr = PyString_InternFromString("__getitem__");
- if (getitemstr == NULL)
- return NULL;
- }
- func = instance_getattr(inst, getitemstr);
- if (func == NULL)
- return NULL;
- arg = Py_BuildValue("(N)", _PySlice_FromIndices(i, j));
- } else
- arg = Py_BuildValue("(nn)", i, j);
-
- if (arg == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- res = PyEval_CallObject(func, arg);
- Py_DECREF(func);
- Py_DECREF(arg);
- return res;
-}
-
-static int
-instance_ass_item(PyInstanceObject *inst, Py_ssize_t i, PyObject *item)
-{
- PyObject *func, *arg, *res;
-
- if (item == NULL) {
- if (delitemstr == NULL) {
- delitemstr = PyString_InternFromString("__delitem__");
- if (delitemstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, delitemstr);
- }
- else {
- if (setitemstr == NULL) {
- setitemstr = PyString_InternFromString("__setitem__");
- if (setitemstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, setitemstr);
- }
- if (func == NULL)
- return -1;
- if (item == NULL)
- arg = PyInt_FromSsize_t(i);
- else
- arg = Py_BuildValue("(nO)", i, item);
- if (arg == NULL) {
- Py_DECREF(func);
- return -1;
- }
- res = PyEval_CallObject(func, arg);
- Py_DECREF(func);
- Py_DECREF(arg);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static int
-instance_ass_slice(PyInstanceObject *inst, Py_ssize_t i, Py_ssize_t j, PyObject *value)
-{
- PyObject *func, *arg, *res;
- static PyObject *setslicestr, *delslicestr;
-
- if (value == NULL) {
- if (delslicestr == NULL) {
- delslicestr =
- PyString_InternFromString("__delslice__");
- if (delslicestr == NULL)
- return -1;
- }
- func = instance_getattr(inst, delslicestr);
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- if (delitemstr == NULL) {
- delitemstr =
- PyString_InternFromString("__delitem__");
- if (delitemstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, delitemstr);
- if (func == NULL)
- return -1;
-
- arg = Py_BuildValue("(N)",
- _PySlice_FromIndices(i, j));
- } else
- arg = Py_BuildValue("(nn)", i, j);
- }
- else {
- if (setslicestr == NULL) {
- setslicestr =
- PyString_InternFromString("__setslice__");
- if (setslicestr == NULL)
- return -1;
- }
- func = instance_getattr(inst, setslicestr);
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- if (setitemstr == NULL) {
- setitemstr =
- PyString_InternFromString("__setitem__");
- if (setitemstr == NULL)
- return -1;
- }
- func = instance_getattr(inst, setitemstr);
- if (func == NULL)
- return -1;
-
- arg = Py_BuildValue("(NO)",
- _PySlice_FromIndices(i, j), value);
- } else
- arg = Py_BuildValue("(nnO)", i, j, value);
- }
- if (arg == NULL) {
- Py_DECREF(func);
- return -1;
- }
- res = PyEval_CallObject(func, arg);
- Py_DECREF(func);
- Py_DECREF(arg);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static int
-instance_contains(PyInstanceObject *inst, PyObject *member)
-{
- static PyObject *__contains__;
- PyObject *func;
-
- /* Try __contains__ first.
- * If that can't be done, try iterator-based searching.
- */
-
- if(__contains__ == NULL) {
- __contains__ = PyString_InternFromString("__contains__");
- if(__contains__ == NULL)
- return -1;
- }
- func = instance_getattr(inst, __contains__);
- if (func) {
- PyObject *res;
- int ret;
- PyObject *arg = PyTuple_Pack(1, member);
- if(arg == NULL) {
- Py_DECREF(func);
- return -1;
- }
- res = PyEval_CallObject(func, arg);
- Py_DECREF(func);
- Py_DECREF(arg);
- if(res == NULL)
- return -1;
- ret = PyObject_IsTrue(res);
- Py_DECREF(res);
- return ret;
- }
-
- /* Couldn't find __contains__. */
- if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
- Py_ssize_t rc;
- /* Assume the failure was simply due to that there is no
- * __contains__ attribute, and try iterating instead.
- */
- PyErr_Clear();
- rc = _PySequence_IterSearch((PyObject *)inst, member,
- PY_ITERSEARCH_CONTAINS);
- if (rc >= 0)
- return rc > 0;
- }
- return -1;
-}
-
-static PySequenceMethods
-instance_as_sequence = {
- (lenfunc)instance_length, /* sq_length */
- 0, /* sq_concat */
- 0, /* sq_repeat */
- (ssizeargfunc)instance_item, /* sq_item */
- (ssizessizeargfunc)instance_slice, /* sq_slice */
- (ssizeobjargproc)instance_ass_item, /* sq_ass_item */
- (ssizessizeobjargproc)instance_ass_slice,/* sq_ass_slice */
- (objobjproc)instance_contains, /* sq_contains */
-};
-
-static PyObject *
-generic_unary_op(PyInstanceObject *self, PyObject *methodname)
-{
- PyObject *func, *res;
-
- if ((func = instance_getattr(self, methodname)) == NULL)
- return NULL;
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- return res;
-}
-
-static PyObject *
-generic_binary_op(PyObject *v, PyObject *w, char *opname)
-{
- PyObject *result;
- PyObject *args;
- PyObject *func = PyObject_GetAttrString(v, opname);
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- args = PyTuple_Pack(1, w);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObject(func, args);
- Py_DECREF(args);
- Py_DECREF(func);
- return result;
-}
-
-
-static PyObject *coerce_obj;
-
-/* Try one half of a binary operator involving a class instance. */
-static PyObject *
-half_binop(PyObject *v, PyObject *w, char *opname, binaryfunc thisfunc,
- int swapped)
-{
- PyObject *args;
- PyObject *coercefunc;
- PyObject *coerced = NULL;
- PyObject *v1;
- PyObject *result;
-
- if (!PyInstance_Check(v)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- if (coerce_obj == NULL) {
- coerce_obj = PyString_InternFromString("__coerce__");
- if (coerce_obj == NULL)
- return NULL;
- }
- coercefunc = PyObject_GetAttr(v, coerce_obj);
- if (coercefunc == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- return generic_binary_op(v, w, opname);
- }
-
- args = PyTuple_Pack(1, w);
- if (args == NULL) {
- Py_DECREF(coercefunc);
- return NULL;
- }
- coerced = PyEval_CallObject(coercefunc, args);
- Py_DECREF(args);
- Py_DECREF(coercefunc);
- if (coerced == NULL) {
- return NULL;
- }
- if (coerced == Py_None || coerced == Py_NotImplemented) {
- Py_DECREF(coerced);
- return generic_binary_op(v, w, opname);
- }
- if (!PyTuple_Check(coerced) || PyTuple_Size(coerced) != 2) {
- Py_DECREF(coerced);
- PyErr_SetString(PyExc_TypeError,
- "coercion should return None or 2-tuple");
- return NULL;
- }
- v1 = PyTuple_GetItem(coerced, 0);
- w = PyTuple_GetItem(coerced, 1);
- if (v1->ob_type == v->ob_type && PyInstance_Check(v)) {
- /* prevent recursion if __coerce__ returns self as the first
- * argument */
- result = generic_binary_op(v1, w, opname);
- } else {
- if (Py_EnterRecursiveCall(" after coercion"))
- return NULL;
- if (swapped)
- result = (thisfunc)(w, v1);
- else
- result = (thisfunc)(v1, w);
- Py_LeaveRecursiveCall();
- }
- Py_DECREF(coerced);
- return result;
-}
-
-/* Implement a binary operator involving at least one class instance. */
-static PyObject *
-do_binop(PyObject *v, PyObject *w, char *opname, char *ropname,
- binaryfunc thisfunc)
-{
- PyObject *result = half_binop(v, w, opname, thisfunc, 0);
- if (result == Py_NotImplemented) {
- Py_DECREF(result);
- result = half_binop(w, v, ropname, thisfunc, 1);
- }
- return result;
-}
-
-static PyObject *
-do_binop_inplace(PyObject *v, PyObject *w, char *iopname, char *opname,
- char *ropname, binaryfunc thisfunc)
-{
- PyObject *result = half_binop(v, w, iopname, thisfunc, 0);
- if (result == Py_NotImplemented) {
- Py_DECREF(result);
- result = do_binop(v, w, opname, ropname, thisfunc);
- }
- return result;
-}
-
-static int
-instance_coerce(PyObject **pv, PyObject **pw)
-{
- PyObject *v = *pv;
- PyObject *w = *pw;
- PyObject *coercefunc;
- PyObject *args;
- PyObject *coerced;
-
- if (coerce_obj == NULL) {
- coerce_obj = PyString_InternFromString("__coerce__");
- if (coerce_obj == NULL)
- return -1;
- }
- coercefunc = PyObject_GetAttr(v, coerce_obj);
- if (coercefunc == NULL) {
- /* No __coerce__ method */
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- return 1;
- }
- /* Has __coerce__ method: call it */
- args = PyTuple_Pack(1, w);
- if (args == NULL) {
- return -1;
- }
- coerced = PyEval_CallObject(coercefunc, args);
- Py_DECREF(args);
- Py_DECREF(coercefunc);
- if (coerced == NULL) {
- /* __coerce__ call raised an exception */
- return -1;
- }
- if (coerced == Py_None || coerced == Py_NotImplemented) {
- /* __coerce__ says "I can't do it" */
- Py_DECREF(coerced);
- return 1;
- }
- if (!PyTuple_Check(coerced) || PyTuple_Size(coerced) != 2) {
- /* __coerce__ return value is malformed */
- Py_DECREF(coerced);
- PyErr_SetString(PyExc_TypeError,
- "coercion should return None or 2-tuple");
- return -1;
- }
- /* __coerce__ returned two new values */
- *pv = PyTuple_GetItem(coerced, 0);
- *pw = PyTuple_GetItem(coerced, 1);
- Py_INCREF(*pv);
- Py_INCREF(*pw);
- Py_DECREF(coerced);
- return 0;
-}
-
-#define UNARY(funcname, methodname) \
-static PyObject *funcname(PyInstanceObject *self) { \
- static PyObject *o; \
- if (o == NULL) { o = PyString_InternFromString(methodname); \
- if (o == NULL) return NULL; } \
- return generic_unary_op(self, o); \
-}
-
-#define BINARY(f, m, n) \
-static PyObject *f(PyObject *v, PyObject *w) { \
- return do_binop(v, w, "__" m "__", "__r" m "__", n); \
-}
-
-#define BINARY_INPLACE(f, m, n) \
-static PyObject *f(PyObject *v, PyObject *w) { \
- return do_binop_inplace(v, w, "__i" m "__", "__" m "__", \
- "__r" m "__", n); \
-}
-
-UNARY(instance_neg, "__neg__")
-UNARY(instance_pos, "__pos__")
-UNARY(instance_abs, "__abs__")
-
-BINARY(instance_or, "or", PyNumber_Or)
-BINARY(instance_and, "and", PyNumber_And)
-BINARY(instance_xor, "xor", PyNumber_Xor)
-BINARY(instance_lshift, "lshift", PyNumber_Lshift)
-BINARY(instance_rshift, "rshift", PyNumber_Rshift)
-BINARY(instance_add, "add", PyNumber_Add)
-BINARY(instance_sub, "sub", PyNumber_Subtract)
-BINARY(instance_mul, "mul", PyNumber_Multiply)
-BINARY(instance_div, "div", PyNumber_Divide)
-BINARY(instance_mod, "mod", PyNumber_Remainder)
-BINARY(instance_divmod, "divmod", PyNumber_Divmod)
-BINARY(instance_floordiv, "floordiv", PyNumber_FloorDivide)
-BINARY(instance_truediv, "truediv", PyNumber_TrueDivide)
-
-BINARY_INPLACE(instance_ior, "or", PyNumber_InPlaceOr)
-BINARY_INPLACE(instance_ixor, "xor", PyNumber_InPlaceXor)
-BINARY_INPLACE(instance_iand, "and", PyNumber_InPlaceAnd)
-BINARY_INPLACE(instance_ilshift, "lshift", PyNumber_InPlaceLshift)
-BINARY_INPLACE(instance_irshift, "rshift", PyNumber_InPlaceRshift)
-BINARY_INPLACE(instance_iadd, "add", PyNumber_InPlaceAdd)
-BINARY_INPLACE(instance_isub, "sub", PyNumber_InPlaceSubtract)
-BINARY_INPLACE(instance_imul, "mul", PyNumber_InPlaceMultiply)
-BINARY_INPLACE(instance_idiv, "div", PyNumber_InPlaceDivide)
-BINARY_INPLACE(instance_imod, "mod", PyNumber_InPlaceRemainder)
-BINARY_INPLACE(instance_ifloordiv, "floordiv", PyNumber_InPlaceFloorDivide)
-BINARY_INPLACE(instance_itruediv, "truediv", PyNumber_InPlaceTrueDivide)
-
-/* Try a 3-way comparison, returning an int; v is an instance. Return:
- -2 for an exception;
- -1 if v < w;
- 0 if v == w;
- 1 if v > w;
- 2 if this particular 3-way comparison is not implemented or undefined.
-*/
-static int
-half_cmp(PyObject *v, PyObject *w)
-{
- static PyObject *cmp_obj;
- PyObject *args;
- PyObject *cmp_func;
- PyObject *result;
- long l;
-
- assert(PyInstance_Check(v));
-
- if (cmp_obj == NULL) {
- cmp_obj = PyString_InternFromString("__cmp__");
- if (cmp_obj == NULL)
- return -2;
- }
-
- cmp_func = PyObject_GetAttr(v, cmp_obj);
- if (cmp_func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -2;
- PyErr_Clear();
- return 2;
- }
-
- args = PyTuple_Pack(1, w);
- if (args == NULL) {
- Py_DECREF(cmp_func);
- return -2;
- }
-
- result = PyEval_CallObject(cmp_func, args);
- Py_DECREF(args);
- Py_DECREF(cmp_func);
-
- if (result == NULL)
- return -2;
-
- if (result == Py_NotImplemented) {
- Py_DECREF(result);
- return 2;
- }
-
- l = PyInt_AsLong(result);
- Py_DECREF(result);
- if (l == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError,
- "comparison did not return an int");
- return -2;
- }
-
- return l < 0 ? -1 : l > 0 ? 1 : 0;
-}
-
-/* Try a 3-way comparison, returning an int; either v or w is an instance.
- We first try a coercion. Return:
- -2 for an exception;
- -1 if v < w;
- 0 if v == w;
- 1 if v > w;
- 2 if this particular 3-way comparison is not implemented or undefined.
- THIS IS ONLY CALLED FROM object.c!
-*/
-static int
-instance_compare(PyObject *v, PyObject *w)
-{
- int c;
-
- c = PyNumber_CoerceEx(&v, &w);
- if (c < 0)
- return -2;
- if (c == 0) {
- /* If neither is now an instance, use regular comparison */
- if (!PyInstance_Check(v) && !PyInstance_Check(w)) {
- c = PyObject_Compare(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- if (PyErr_Occurred())
- return -2;
- return c < 0 ? -1 : c > 0 ? 1 : 0;
- }
- }
- else {
- /* The coercion didn't do anything.
- Treat this the same as returning v and w unchanged. */
- Py_INCREF(v);
- Py_INCREF(w);
- }
-
- if (PyInstance_Check(v)) {
- c = half_cmp(v, w);
- if (c <= 1) {
- Py_DECREF(v);
- Py_DECREF(w);
- return c;
- }
- }
- if (PyInstance_Check(w)) {
- c = half_cmp(w, v);
- if (c <= 1) {
- Py_DECREF(v);
- Py_DECREF(w);
- if (c >= -1)
- c = -c;
- return c;
- }
- }
- Py_DECREF(v);
- Py_DECREF(w);
- return 2;
-}
-
-static int
-instance_nonzero(PyInstanceObject *self)
-{
- PyObject *func, *res;
- long outcome;
- static PyObject *nonzerostr;
-
- if (nonzerostr == NULL) {
- nonzerostr = PyString_InternFromString("__nonzero__");
- if (nonzerostr == NULL)
- return -1;
- }
- if ((func = instance_getattr(self, nonzerostr)) == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- if (lenstr == NULL) {
- lenstr = PyString_InternFromString("__len__");
- if (lenstr == NULL)
- return -1;
- }
- if ((func = instance_getattr(self, lenstr)) == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return -1;
- PyErr_Clear();
- /* Fall back to the default behavior:
- all instances are nonzero */
- return 1;
- }
- }
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- if (res == NULL)
- return -1;
- if (!PyInt_Check(res)) {
- Py_DECREF(res);
- PyErr_SetString(PyExc_TypeError,
- "__nonzero__ should return an int");
- return -1;
- }
- outcome = PyInt_AsLong(res);
- Py_DECREF(res);
- if (outcome < 0) {
- PyErr_SetString(PyExc_ValueError,
- "__nonzero__ should return >= 0");
- return -1;
- }
- return outcome > 0;
-}
-
-static PyObject *
-instance_index(PyInstanceObject *self)
-{
- PyObject *func, *res;
- static PyObject *indexstr = NULL;
-
- if (indexstr == NULL) {
- indexstr = PyString_InternFromString("__index__");
- if (indexstr == NULL)
- return NULL;
- }
- if ((func = instance_getattr(self, indexstr)) == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- PyErr_SetString(PyExc_TypeError,
- "object cannot be interpreted as an index");
- return NULL;
- }
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- return res;
-}
-
-
-UNARY(instance_invert, "__invert__")
-UNARY(instance_int, "__int__")
-UNARY(instance_long, "__long__")
-UNARY(instance_float, "__float__")
-UNARY(instance_oct, "__oct__")
-UNARY(instance_hex, "__hex__")
-
-static PyObject *
-bin_power(PyObject *v, PyObject *w)
-{
- return PyNumber_Power(v, w, Py_None);
-}
-
-/* This version is for ternary calls only (z != None) */
-static PyObject *
-instance_pow(PyObject *v, PyObject *w, PyObject *z)
-{
- if (z == Py_None) {
- return do_binop(v, w, "__pow__", "__rpow__", bin_power);
- }
- else {
- PyObject *func;
- PyObject *args;
- PyObject *result;
-
- /* XXX Doesn't do coercions... */
- func = PyObject_GetAttrString(v, "__pow__");
- if (func == NULL)
- return NULL;
- args = PyTuple_Pack(2, w, z);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObject(func, args);
- Py_DECREF(func);
- Py_DECREF(args);
- return result;
- }
-}
-
-static PyObject *
-bin_inplace_power(PyObject *v, PyObject *w)
-{
- return PyNumber_InPlacePower(v, w, Py_None);
-}
-
-
-static PyObject *
-instance_ipow(PyObject *v, PyObject *w, PyObject *z)
-{
- if (z == Py_None) {
- return do_binop_inplace(v, w, "__ipow__", "__pow__",
- "__rpow__", bin_inplace_power);
- }
- else {
- /* XXX Doesn't do coercions... */
- PyObject *func;
- PyObject *args;
- PyObject *result;
-
- func = PyObject_GetAttrString(v, "__ipow__");
- if (func == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- return instance_pow(v, w, z);
- }
- args = PyTuple_Pack(2, w, z);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObject(func, args);
- Py_DECREF(func);
- Py_DECREF(args);
- return result;
- }
-}
-
-
-/* Map rich comparison operators to their __xx__ namesakes */
-#define NAME_OPS 6
-static PyObject **name_op = NULL;
-
-static int
-init_name_op(void)
-{
- int i;
- char *_name_op[] = {
- "__lt__",
- "__le__",
- "__eq__",
- "__ne__",
- "__gt__",
- "__ge__",
- };
-
- name_op = (PyObject **)malloc(sizeof(PyObject *) * NAME_OPS);
- if (name_op == NULL)
- return -1;
- for (i = 0; i < NAME_OPS; ++i) {
- name_op[i] = PyString_InternFromString(_name_op[i]);
- if (name_op[i] == NULL)
- return -1;
- }
- return 0;
-}
-
-static PyObject *
-half_richcompare(PyObject *v, PyObject *w, int op)
-{
- PyObject *method;
- PyObject *args;
- PyObject *res;
-
- assert(PyInstance_Check(v));
-
- if (name_op == NULL) {
- if (init_name_op() < 0)
- return NULL;
- }
- /* If the instance doesn't define an __getattr__ method, use
- instance_getattr2 directly because it will not set an
- exception on failure. */
- if (((PyInstanceObject *)v)->in_class->cl_getattr == NULL)
- method = instance_getattr2((PyInstanceObject *)v,
- name_op[op]);
- else
- method = PyObject_GetAttr(v, name_op[op]);
- if (method == NULL) {
- if (PyErr_Occurred()) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- }
- res = Py_NotImplemented;
- Py_INCREF(res);
- return res;
- }
-
- args = PyTuple_Pack(1, w);
- if (args == NULL) {
- Py_DECREF(method);
- return NULL;
- }
-
- res = PyEval_CallObject(method, args);
- Py_DECREF(args);
- Py_DECREF(method);
-
- return res;
-}
-
-static PyObject *
-instance_richcompare(PyObject *v, PyObject *w, int op)
-{
- PyObject *res;
-
- if (PyInstance_Check(v)) {
- res = half_richcompare(v, w, op);
- if (res != Py_NotImplemented)
- return res;
- Py_DECREF(res);
- }
-
- if (PyInstance_Check(w)) {
- res = half_richcompare(w, v, _Py_SwappedOp[op]);
- if (res != Py_NotImplemented)
- return res;
- Py_DECREF(res);
- }
-
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-
-/* Get the iterator */
-static PyObject *
-instance_getiter(PyInstanceObject *self)
-{
- PyObject *func;
-
- if (iterstr == NULL) {
- iterstr = PyString_InternFromString("__iter__");
- if (iterstr == NULL)
- return NULL;
- }
- if (getitemstr == NULL) {
- getitemstr = PyString_InternFromString("__getitem__");
- if (getitemstr == NULL)
- return NULL;
- }
-
- if ((func = instance_getattr(self, iterstr)) != NULL) {
- PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- if (res != NULL && !PyIter_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "__iter__ returned non-iterator "
- "of type '%.100s'",
- res->ob_type->tp_name);
- Py_DECREF(res);
- res = NULL;
- }
- return res;
- }
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- if ((func = instance_getattr(self, getitemstr)) == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "iteration over non-sequence");
- return NULL;
- }
- Py_DECREF(func);
- return PySeqIter_New((PyObject *)self);
-}
-
-
-/* Call the iterator's next */
-static PyObject *
-instance_iternext(PyInstanceObject *self)
-{
- PyObject *func;
-
- if (nextstr == NULL) {
- nextstr = PyString_InternFromString("next");
- if (nextstr == NULL)
- return NULL;
- }
-
- if ((func = instance_getattr(self, nextstr)) != NULL) {
- PyObject *res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- if (res != NULL) {
- return res;
- }
- if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- PyErr_Clear();
- return NULL;
- }
- return NULL;
- }
- PyErr_SetString(PyExc_TypeError, "instance has no next() method");
- return NULL;
-}
-
-static PyObject *
-instance_call(PyObject *func, PyObject *arg, PyObject *kw)
-{
- PyObject *res, *call = PyObject_GetAttrString(func, "__call__");
- if (call == NULL) {
- PyInstanceObject *inst = (PyInstanceObject*) func;
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- PyErr_Format(PyExc_AttributeError,
- "%.200s instance has no __call__ method",
- PyString_AsString(inst->in_class->cl_name));
- return NULL;
- }
- /* We must check and increment the recursion depth here. Scenario:
- class A:
- pass
- A.__call__ = A() # that's right
- a = A() # ok
- a() # infinite recursion
- This bounces between instance_call() and PyObject_Call() without
- ever hitting eval_frame() (which has the main recursion check). */
- if (Py_EnterRecursiveCall(" in __call__")) {
- res = NULL;
- }
- else {
- res = PyObject_Call(call, arg, kw);
- Py_LeaveRecursiveCall();
- }
- Py_DECREF(call);
- return res;
-}
-
-
-static PyNumberMethods instance_as_number = {
- instance_add, /* nb_add */
- instance_sub, /* nb_subtract */
- instance_mul, /* nb_multiply */
- instance_div, /* nb_divide */
- instance_mod, /* nb_remainder */
- instance_divmod, /* nb_divmod */
- instance_pow, /* nb_power */
- (unaryfunc)instance_neg, /* nb_negative */
- (unaryfunc)instance_pos, /* nb_positive */
- (unaryfunc)instance_abs, /* nb_absolute */
- (inquiry)instance_nonzero, /* nb_nonzero */
- (unaryfunc)instance_invert, /* nb_invert */
- instance_lshift, /* nb_lshift */
- instance_rshift, /* nb_rshift */
- instance_and, /* nb_and */
- instance_xor, /* nb_xor */
- instance_or, /* nb_or */
- instance_coerce, /* nb_coerce */
- (unaryfunc)instance_int, /* nb_int */
- (unaryfunc)instance_long, /* nb_long */
- (unaryfunc)instance_float, /* nb_float */
- (unaryfunc)instance_oct, /* nb_oct */
- (unaryfunc)instance_hex, /* nb_hex */
- instance_iadd, /* nb_inplace_add */
- instance_isub, /* nb_inplace_subtract */
- instance_imul, /* nb_inplace_multiply */
- instance_idiv, /* nb_inplace_divide */
- instance_imod, /* nb_inplace_remainder */
- instance_ipow, /* nb_inplace_power */
- instance_ilshift, /* nb_inplace_lshift */
- instance_irshift, /* nb_inplace_rshift */
- instance_iand, /* nb_inplace_and */
- instance_ixor, /* nb_inplace_xor */
- instance_ior, /* nb_inplace_or */
- instance_floordiv, /* nb_floor_divide */
- instance_truediv, /* nb_true_divide */
- instance_ifloordiv, /* nb_inplace_floor_divide */
- instance_itruediv, /* nb_inplace_true_divide */
- (unaryfunc)instance_index, /* nb_index */
-};
-
-PyTypeObject PyInstance_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "instance",
- sizeof(PyInstanceObject),
- 0,
- (destructor)instance_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- instance_compare, /* tp_compare */
- (reprfunc)instance_repr, /* tp_repr */
- &instance_as_number, /* tp_as_number */
- &instance_as_sequence, /* tp_as_sequence */
- &instance_as_mapping, /* tp_as_mapping */
- (hashfunc)instance_hash, /* tp_hash */
- instance_call, /* tp_call */
- (reprfunc)instance_str, /* tp_str */
- (getattrofunc)instance_getattr, /* tp_getattro */
- (setattrofunc)instance_setattr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES,/*tp_flags*/
- instance_doc, /* tp_doc */
- (traverseproc)instance_traverse, /* tp_traverse */
- 0, /* tp_clear */
- instance_richcompare, /* tp_richcompare */
- offsetof(PyInstanceObject, in_weakreflist), /* tp_weaklistoffset */
- (getiterfunc)instance_getiter, /* tp_iter */
- (iternextfunc)instance_iternext, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- instance_new, /* tp_new */
-};
-
-
-/* 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
-*/
-
-static PyMethodObject *free_list;
-
-PyObject *
-PyMethod_New(PyObject *func, PyObject *self, PyObject *klass)
-{
- register PyMethodObject *im;
- if (!PyCallable_Check(func)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- im = free_list;
- if (im != NULL) {
- free_list = (PyMethodObject *)(im->im_self);
- PyObject_INIT(im, &PyMethod_Type);
- }
- else {
- im = PyObject_GC_New(PyMethodObject, &PyMethod_Type);
- if (im == NULL)
- return NULL;
- }
- im->im_weakreflist = NULL;
- Py_INCREF(func);
- im->im_func = func;
- Py_XINCREF(self);
- im->im_self = self;
- Py_XINCREF(klass);
- im->im_class = klass;
- _PyObject_GC_TRACK(im);
- return (PyObject *)im;
-}
-
-/* Descriptors for PyMethod attributes */
-
-/* im_class, im_func and im_self are stored in the PyMethod object */
-
-#define OFF(x) offsetof(PyMethodObject, x)
-
-static PyMemberDef instancemethod_memberlist[] = {
- {"im_class", T_OBJECT, OFF(im_class), READONLY|RESTRICTED,
- "the class associated with a method"},
- {"im_func", T_OBJECT, OFF(im_func), READONLY|RESTRICTED,
- "the function (or other callable) implementing a method"},
- {"im_self", T_OBJECT, OFF(im_self), READONLY|RESTRICTED,
- "the instance to which a method is bound; None for unbound methods"},
- {NULL} /* Sentinel */
-};
-
-/* Christian Tismer argued convincingly that method attributes should
- (nearly) always override function attributes.
- The one exception is __doc__; there's a default __doc__ which
- should only be used for the class, not for instances */
-
-static PyObject *
-instancemethod_get_doc(PyMethodObject *im, void *context)
-{
- static PyObject *docstr;
- if (docstr == NULL) {
- docstr= PyString_InternFromString("__doc__");
- if (docstr == NULL)
- return NULL;
- }
- return PyObject_GetAttr(im->im_func, docstr);
-}
-
-static PyGetSetDef instancemethod_getset[] = {
- {"__doc__", (getter)instancemethod_get_doc, NULL, NULL},
- {0}
-};
-
-static PyObject *
-instancemethod_getattro(PyObject *obj, PyObject *name)
-{
- PyMethodObject *im = (PyMethodObject *)obj;
- PyTypeObject *tp = obj->ob_type;
- PyObject *descr = NULL;
-
- if (PyType_HasFeature(tp, Py_TPFLAGS_HAVE_CLASS)) {
- if (tp->tp_dict == NULL) {
- if (PyType_Ready(tp) < 0)
- return NULL;
- }
- descr = _PyType_Lookup(tp, name);
- }
-
- if (descr != NULL) {
- descrgetfunc f = TP_DESCR_GET(descr->ob_type);
- if (f != NULL)
- return f(descr, obj, (PyObject *)obj->ob_type);
- else {
- Py_INCREF(descr);
- return descr;
- }
- }
-
- return PyObject_GetAttr(im->im_func, name);
-}
-
-PyDoc_STRVAR(instancemethod_doc,
-"instancemethod(function, instance, class)\n\
-\n\
-Create an instance method object.");
-
-static PyObject *
-instancemethod_new(PyTypeObject* type, PyObject* args, PyObject *kw)
-{
- PyObject *func;
- PyObject *self;
- PyObject *classObj = NULL;
-
- if (!_PyArg_NoKeywords("instancemethod", kw))
- return NULL;
- if (!PyArg_UnpackTuple(args, "instancemethod", 2, 3,
- &func, &self, &classObj))
- return NULL;
- if (!PyCallable_Check(func)) {
- PyErr_SetString(PyExc_TypeError,
- "first argument must be callable");
- return NULL;
- }
- if (self == Py_None)
- self = NULL;
- if (self == NULL && classObj == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "unbound methods must have non-NULL im_class");
- return NULL;
- }
-
- return PyMethod_New(func, self, classObj);
-}
-
-static void
-instancemethod_dealloc(register PyMethodObject *im)
-{
- _PyObject_GC_UNTRACK(im);
- if (im->im_weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *)im);
- Py_DECREF(im->im_func);
- Py_XDECREF(im->im_self);
- Py_XDECREF(im->im_class);
- im->im_self = (PyObject *)free_list;
- free_list = im;
-}
-
-static int
-instancemethod_compare(PyMethodObject *a, PyMethodObject *b)
-{
- int cmp;
- cmp = PyObject_Compare(a->im_func, b->im_func);
- if (cmp)
- return cmp;
-
- if (a->im_self == b->im_self)
- return 0;
- if (a->im_self == NULL || b->im_self == NULL)
- return (a->im_self < b->im_self) ? -1 : 1;
- else
- return PyObject_Compare(a->im_self, b->im_self);
-}
-
-static PyObject *
-instancemethod_repr(PyMethodObject *a)
-{
- PyObject *self = a->im_self;
- PyObject *func = a->im_func;
- PyObject *klass = a->im_class;
- PyObject *funcname = NULL, *klassname = NULL, *result = NULL;
- char *sfuncname = "?", *sklassname = "?";
-
- funcname = PyObject_GetAttrString(func, "__name__");
- if (funcname == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- }
- else if (!PyString_Check(funcname)) {
- Py_DECREF(funcname);
- funcname = NULL;
- }
- else
- sfuncname = PyString_AS_STRING(funcname);
- if (klass == NULL)
- klassname = NULL;
- else {
- klassname = PyObject_GetAttrString(klass, "__name__");
- if (klassname == NULL) {
- if (!PyErr_ExceptionMatches(PyExc_AttributeError))
- return NULL;
- PyErr_Clear();
- }
- else if (!PyString_Check(klassname)) {
- Py_DECREF(klassname);
- klassname = NULL;
- }
- else
- sklassname = PyString_AS_STRING(klassname);
- }
- if (self == NULL)
- result = PyString_FromFormat("<unbound method %s.%s>",
- sklassname, sfuncname);
- else {
- /* XXX Shouldn't use repr() here! */
- PyObject *selfrepr = PyObject_Repr(self);
- if (selfrepr == NULL)
- goto fail;
- if (!PyString_Check(selfrepr)) {
- Py_DECREF(selfrepr);
- goto fail;
- }
- result = PyString_FromFormat("<bound method %s.%s of %s>",
- sklassname, sfuncname,
- PyString_AS_STRING(selfrepr));
- Py_DECREF(selfrepr);
- }
- fail:
- Py_XDECREF(funcname);
- Py_XDECREF(klassname);
- return result;
-}
-
-static long
-instancemethod_hash(PyMethodObject *a)
-{
- long x, y;
- if (a->im_self == NULL)
- x = PyObject_Hash(Py_None);
- else
- x = PyObject_Hash(a->im_self);
- if (x == -1)
- return -1;
- y = PyObject_Hash(a->im_func);
- if (y == -1)
- return -1;
- x = x ^ y;
- if (x == -1)
- x = -2;
- return x;
-}
-
-static int
-instancemethod_traverse(PyMethodObject *im, visitproc visit, void *arg)
-{
- Py_VISIT(im->im_func);
- Py_VISIT(im->im_self);
- Py_VISIT(im->im_class);
- return 0;
-}
-
-static void
-getclassname(PyObject *klass, char *buf, int bufsize)
-{
- PyObject *name;
-
- assert(bufsize > 1);
- strcpy(buf, "?"); /* Default outcome */
- if (klass == NULL)
- return;
- name = PyObject_GetAttrString(klass, "__name__");
- if (name == NULL) {
- /* This function cannot return an exception */
- PyErr_Clear();
- return;
- }
- if (PyString_Check(name)) {
- strncpy(buf, PyString_AS_STRING(name), bufsize);
- buf[bufsize-1] = '\0';
- }
- Py_DECREF(name);
-}
-
-static void
-getinstclassname(PyObject *inst, char *buf, int bufsize)
-{
- PyObject *klass;
-
- if (inst == NULL) {
- assert(bufsize > 0 && (size_t)bufsize > strlen("nothing"));
- strcpy(buf, "nothing");
- return;
- }
-
- klass = PyObject_GetAttrString(inst, "__class__");
- if (klass == NULL) {
- /* This function cannot return an exception */
- PyErr_Clear();
- klass = (PyObject *)(inst->ob_type);
- Py_INCREF(klass);
- }
- getclassname(klass, buf, bufsize);
- Py_XDECREF(klass);
-}
-
-static PyObject *
-instancemethod_call(PyObject *func, PyObject *arg, PyObject *kw)
-{
- PyObject *self = PyMethod_GET_SELF(func);
- PyObject *klass = PyMethod_GET_CLASS(func);
- PyObject *result;
-
- func = PyMethod_GET_FUNCTION(func);
- if (self == NULL) {
- /* Unbound methods must be called with an instance of
- the class (or a derived class) as first argument */
- int ok;
- if (PyTuple_Size(arg) >= 1)
- self = PyTuple_GET_ITEM(arg, 0);
- if (self == NULL)
- ok = 0;
- else {
- ok = PyObject_IsInstance(self, klass);
- if (ok < 0)
- return NULL;
- }
- if (!ok) {
- char clsbuf[256];
- char instbuf[256];
- getclassname(klass, clsbuf, sizeof(clsbuf));
- getinstclassname(self, instbuf, sizeof(instbuf));
- PyErr_Format(PyExc_TypeError,
- "unbound method %s%s must be called with "
- "%s instance as first argument "
- "(got %s%s instead)",
- PyEval_GetFuncName(func),
- PyEval_GetFuncDesc(func),
- clsbuf,
- instbuf,
- self == NULL ? "" : " instance");
- return NULL;
- }
- Py_INCREF(arg);
- }
- else {
- Py_ssize_t argcount = PyTuple_Size(arg);
- PyObject *newarg = PyTuple_New(argcount + 1);
- int i;
- if (newarg == NULL)
- return NULL;
- Py_INCREF(self);
- PyTuple_SET_ITEM(newarg, 0, self);
- for (i = 0; i < argcount; i++) {
- PyObject *v = PyTuple_GET_ITEM(arg, i);
- Py_XINCREF(v);
- PyTuple_SET_ITEM(newarg, i+1, v);
- }
- arg = newarg;
- }
- result = PyObject_Call((PyObject *)func, arg, kw);
- Py_DECREF(arg);
- return result;
-}
-
-static PyObject *
-instancemethod_descr_get(PyObject *meth, PyObject *obj, PyObject *cls)
-{
- /* Don't rebind an already bound method, or an unbound method
- of a class that's not a base class of cls. */
-
- if (PyMethod_GET_SELF(meth) != NULL) {
- /* Already bound */
- Py_INCREF(meth);
- return meth;
- }
- /* No, it is an unbound method */
- if (PyMethod_GET_CLASS(meth) != NULL && cls != NULL) {
- /* Do subclass test. If it fails, return meth unchanged. */
- int ok = PyObject_IsSubclass(cls, PyMethod_GET_CLASS(meth));
- if (ok < 0)
- return NULL;
- if (!ok) {
- Py_INCREF(meth);
- return meth;
- }
- }
- /* Bind it to obj */
- return PyMethod_New(PyMethod_GET_FUNCTION(meth), obj, cls);
-}
-
-PyTypeObject PyMethod_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "instancemethod",
- sizeof(PyMethodObject),
- 0,
- (destructor)instancemethod_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)instancemethod_compare, /* tp_compare */
- (reprfunc)instancemethod_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)instancemethod_hash, /* tp_hash */
- instancemethod_call, /* tp_call */
- 0, /* tp_str */
- instancemethod_getattro, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
- instancemethod_doc, /* tp_doc */
- (traverseproc)instancemethod_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(PyMethodObject, im_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- instancemethod_memberlist, /* tp_members */
- instancemethod_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- instancemethod_descr_get, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- instancemethod_new, /* tp_new */
-};
-
-/* Clear out the free list */
-
-void
-PyMethod_Fini(void)
-{
- while (free_list) {
- PyMethodObject *im = free_list;
- free_list = (PyMethodObject *)(im->im_self);
- PyObject_GC_Del(im);
- }
-}
diff --git a/sys/src/cmd/python/Objects/cobject.c b/sys/src/cmd/python/Objects/cobject.c
deleted file mode 100644
index b2cae9a40..000000000
--- a/sys/src/cmd/python/Objects/cobject.c
+++ /dev/null
@@ -1,161 +0,0 @@
-
-/* Wrap void* pointers to be passed between C modules */
-
-#include "Python.h"
-
-
-/* Declarations for objects of type PyCObject */
-
-typedef void (*destructor1)(void *);
-typedef void (*destructor2)(void *, void*);
-
-typedef struct {
- PyObject_HEAD
- void *cobject;
- void *desc;
- void (*destructor)(void *);
-} PyCObject;
-
-PyObject *
-PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *))
-{
- PyCObject *self;
-
- self = PyObject_NEW(PyCObject, &PyCObject_Type);
- if (self == NULL)
- return NULL;
- self->cobject=cobj;
- self->destructor=destr;
- self->desc=NULL;
-
- return (PyObject *)self;
-}
-
-PyObject *
-PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc,
- void (*destr)(void *, void *))
-{
- PyCObject *self;
-
- if (!desc) {
- PyErr_SetString(PyExc_TypeError,
- "PyCObject_FromVoidPtrAndDesc called with null"
- " description");
- return NULL;
- }
- self = PyObject_NEW(PyCObject, &PyCObject_Type);
- if (self == NULL)
- return NULL;
- self->cobject = cobj;
- self->destructor = (destructor1)destr;
- self->desc = desc;
-
- return (PyObject *)self;
-}
-
-void *
-PyCObject_AsVoidPtr(PyObject *self)
-{
- if (self) {
- if (self->ob_type == &PyCObject_Type)
- return ((PyCObject *)self)->cobject;
- PyErr_SetString(PyExc_TypeError,
- "PyCObject_AsVoidPtr with non-C-object");
- }
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_TypeError,
- "PyCObject_AsVoidPtr called with null pointer");
- return NULL;
-}
-
-void *
-PyCObject_GetDesc(PyObject *self)
-{
- if (self) {
- if (self->ob_type == &PyCObject_Type)
- return ((PyCObject *)self)->desc;
- PyErr_SetString(PyExc_TypeError,
- "PyCObject_GetDesc with non-C-object");
- }
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_TypeError,
- "PyCObject_GetDesc called with null pointer");
- return NULL;
-}
-
-void *
-PyCObject_Import(char *module_name, char *name)
-{
- PyObject *m, *c;
- void *r = NULL;
-
- if ((m = PyImport_ImportModule(module_name))) {
- if ((c = PyObject_GetAttrString(m,name))) {
- r = PyCObject_AsVoidPtr(c);
- Py_DECREF(c);
- }
- Py_DECREF(m);
- }
- return r;
-}
-
-int
-PyCObject_SetVoidPtr(PyObject *self, void *cobj)
-{
- PyCObject* cself = (PyCObject*)self;
- if (cself == NULL || !PyCObject_Check(cself) ||
- cself->destructor != NULL) {
- PyErr_SetString(PyExc_TypeError,
- "Invalid call to PyCObject_SetVoidPtr");
- return 0;
- }
- cself->cobject = cobj;
- return 1;
-}
-
-static void
-PyCObject_dealloc(PyCObject *self)
-{
- if (self->destructor) {
- if(self->desc)
- ((destructor2)(self->destructor))(self->cobject, self->desc);
- else
- (self->destructor)(self->cobject);
- }
- PyObject_DEL(self);
-}
-
-
-PyDoc_STRVAR(PyCObject_Type__doc__,
-"C objects to be exported from one extension module to another\n\
-\n\
-C objects are used for communication between extension modules. They\n\
-provide a way for an extension module to export a C interface to other\n\
-extension modules, so that extension modules can use the Python import\n\
-mechanism to link to one another.");
-
-PyTypeObject PyCObject_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /*ob_size*/
- "PyCObject", /*tp_name*/
- sizeof(PyCObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)PyCObject_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- 0, /*tp_flags*/
- PyCObject_Type__doc__ /*tp_doc*/
-};
diff --git a/sys/src/cmd/python/Objects/codeobject.c b/sys/src/cmd/python/Objects/codeobject.c
deleted file mode 100644
index 89871d6cf..000000000
--- a/sys/src/cmd/python/Objects/codeobject.c
+++ /dev/null
@@ -1,590 +0,0 @@
-#include "Python.h"
-#include "code.h"
-#include "structmember.h"
-
-#define NAME_CHARS \
- "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
-
-/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
-
-static int
-all_name_chars(unsigned char *s)
-{
- static char ok_name_char[256];
- static unsigned char *name_chars = (unsigned char *)NAME_CHARS;
-
- if (ok_name_char[*name_chars] == 0) {
- unsigned char *p;
- for (p = name_chars; *p; p++)
- ok_name_char[*p] = 1;
- }
- while (*s) {
- if (ok_name_char[*s++] == 0)
- return 0;
- }
- return 1;
-}
-
-static void
-intern_strings(PyObject *tuple)
-{
- Py_ssize_t i;
-
- for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
- PyObject *v = PyTuple_GET_ITEM(tuple, i);
- if (v == NULL || !PyString_CheckExact(v)) {
- Py_FatalError("non-string found in code slot");
- }
- PyString_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
- }
-}
-
-
-PyCodeObject *
-PyCode_New(int argcount, int nlocals, int stacksize, int flags,
- PyObject *code, PyObject *consts, PyObject *names,
- PyObject *varnames, PyObject *freevars, PyObject *cellvars,
- PyObject *filename, PyObject *name, int firstlineno,
- PyObject *lnotab)
-{
- PyCodeObject *co;
- Py_ssize_t i;
- /* Check argument types */
- if (argcount < 0 || nlocals < 0 ||
- code == NULL ||
- consts == NULL || !PyTuple_Check(consts) ||
- names == NULL || !PyTuple_Check(names) ||
- varnames == NULL || !PyTuple_Check(varnames) ||
- freevars == NULL || !PyTuple_Check(freevars) ||
- cellvars == NULL || !PyTuple_Check(cellvars) ||
- name == NULL || !PyString_Check(name) ||
- filename == NULL || !PyString_Check(filename) ||
- lnotab == NULL || !PyString_Check(lnotab) ||
- !PyObject_CheckReadBuffer(code)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- intern_strings(names);
- intern_strings(varnames);
- intern_strings(freevars);
- intern_strings(cellvars);
- /* Intern selected string constants */
- for (i = PyTuple_Size(consts); --i >= 0; ) {
- PyObject *v = PyTuple_GetItem(consts, i);
- if (!PyString_Check(v))
- continue;
- if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
- continue;
- PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
- }
- co = PyObject_NEW(PyCodeObject, &PyCode_Type);
- if (co != NULL) {
- co->co_argcount = argcount;
- co->co_nlocals = nlocals;
- co->co_stacksize = stacksize;
- co->co_flags = flags;
- Py_INCREF(code);
- co->co_code = code;
- Py_INCREF(consts);
- co->co_consts = consts;
- Py_INCREF(names);
- co->co_names = names;
- Py_INCREF(varnames);
- co->co_varnames = varnames;
- Py_INCREF(freevars);
- co->co_freevars = freevars;
- Py_INCREF(cellvars);
- co->co_cellvars = cellvars;
- Py_INCREF(filename);
- co->co_filename = filename;
- Py_INCREF(name);
- co->co_name = name;
- co->co_firstlineno = firstlineno;
- Py_INCREF(lnotab);
- co->co_lnotab = lnotab;
- co->co_zombieframe = NULL;
- }
- return co;
-}
-
-
-#define OFF(x) offsetof(PyCodeObject, x)
-
-static PyMemberDef code_memberlist[] = {
- {"co_argcount", T_INT, OFF(co_argcount), READONLY},
- {"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
- {"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
- {"co_flags", T_INT, OFF(co_flags), READONLY},
- {"co_code", T_OBJECT, OFF(co_code), READONLY},
- {"co_consts", T_OBJECT, OFF(co_consts), READONLY},
- {"co_names", T_OBJECT, OFF(co_names), READONLY},
- {"co_varnames", T_OBJECT, OFF(co_varnames), READONLY},
- {"co_freevars", T_OBJECT, OFF(co_freevars), READONLY},
- {"co_cellvars", T_OBJECT, OFF(co_cellvars), READONLY},
- {"co_filename", T_OBJECT, OFF(co_filename), READONLY},
- {"co_name", T_OBJECT, OFF(co_name), READONLY},
- {"co_firstlineno", T_INT, OFF(co_firstlineno), READONLY},
- {"co_lnotab", T_OBJECT, OFF(co_lnotab), READONLY},
- {NULL} /* Sentinel */
-};
-
-/* Helper for code_new: return a shallow copy of a tuple that is
- guaranteed to contain exact strings, by converting string subclasses
- to exact strings and complaining if a non-string is found. */
-static PyObject*
-validate_and_copy_tuple(PyObject *tup)
-{
- PyObject *newtuple;
- PyObject *item;
- Py_ssize_t i, len;
-
- len = PyTuple_GET_SIZE(tup);
- newtuple = PyTuple_New(len);
- if (newtuple == NULL)
- return NULL;
-
- for (i = 0; i < len; i++) {
- item = PyTuple_GET_ITEM(tup, i);
- if (PyString_CheckExact(item)) {
- Py_INCREF(item);
- }
- else if (!PyString_Check(item)) {
- PyErr_Format(
- PyExc_TypeError,
- "name tuples must contain only "
- "strings, not '%.500s'",
- item->ob_type->tp_name);
- Py_DECREF(newtuple);
- return NULL;
- }
- else {
- item = PyString_FromStringAndSize(
- PyString_AS_STRING(item),
- PyString_GET_SIZE(item));
- if (item == NULL) {
- Py_DECREF(newtuple);
- return NULL;
- }
- }
- PyTuple_SET_ITEM(newtuple, i, item);
- }
-
- return newtuple;
-}
-
-PyDoc_STRVAR(code_doc,
-"code(argcount, nlocals, stacksize, flags, codestring, constants, names,\n\
- varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])\n\
-\n\
-Create a code object. Not for the faint of heart.");
-
-static PyObject *
-code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
-{
- int argcount;
- int nlocals;
- int stacksize;
- int flags;
- PyObject *co = NULL;
- PyObject *code;
- PyObject *consts;
- PyObject *names, *ournames = NULL;
- PyObject *varnames, *ourvarnames = NULL;
- PyObject *freevars = NULL, *ourfreevars = NULL;
- PyObject *cellvars = NULL, *ourcellvars = NULL;
- PyObject *filename;
- PyObject *name;
- int firstlineno;
- PyObject *lnotab;
-
- if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
- &argcount, &nlocals, &stacksize, &flags,
- &code,
- &PyTuple_Type, &consts,
- &PyTuple_Type, &names,
- &PyTuple_Type, &varnames,
- &filename, &name,
- &firstlineno, &lnotab,
- &PyTuple_Type, &freevars,
- &PyTuple_Type, &cellvars))
- return NULL;
-
- if (argcount < 0) {
- PyErr_SetString(
- PyExc_ValueError,
- "code: argcount must not be negative");
- goto cleanup;
- }
-
- if (nlocals < 0) {
- PyErr_SetString(
- PyExc_ValueError,
- "code: nlocals must not be negative");
- goto cleanup;
- }
-
- ournames = validate_and_copy_tuple(names);
- if (ournames == NULL)
- goto cleanup;
- ourvarnames = validate_and_copy_tuple(varnames);
- if (ourvarnames == NULL)
- goto cleanup;
- if (freevars)
- ourfreevars = validate_and_copy_tuple(freevars);
- else
- ourfreevars = PyTuple_New(0);
- if (ourfreevars == NULL)
- goto cleanup;
- if (cellvars)
- ourcellvars = validate_and_copy_tuple(cellvars);
- else
- ourcellvars = PyTuple_New(0);
- if (ourcellvars == NULL)
- goto cleanup;
-
- co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
- code, consts, ournames, ourvarnames,
- ourfreevars, ourcellvars, filename,
- name, firstlineno, lnotab);
- cleanup:
- Py_XDECREF(ournames);
- Py_XDECREF(ourvarnames);
- Py_XDECREF(ourfreevars);
- Py_XDECREF(ourcellvars);
- return co;
-}
-
-static void
-code_dealloc(PyCodeObject *co)
-{
- Py_XDECREF(co->co_code);
- Py_XDECREF(co->co_consts);
- Py_XDECREF(co->co_names);
- Py_XDECREF(co->co_varnames);
- Py_XDECREF(co->co_freevars);
- Py_XDECREF(co->co_cellvars);
- Py_XDECREF(co->co_filename);
- Py_XDECREF(co->co_name);
- Py_XDECREF(co->co_lnotab);
- if (co->co_zombieframe != NULL)
- PyObject_GC_Del(co->co_zombieframe);
- PyObject_DEL(co);
-}
-
-static PyObject *
-code_repr(PyCodeObject *co)
-{
- char buf[500];
- int lineno = -1;
- char *filename = "???";
- char *name = "???";
-
- if (co->co_firstlineno != 0)
- lineno = co->co_firstlineno;
- if (co->co_filename && PyString_Check(co->co_filename))
- filename = PyString_AS_STRING(co->co_filename);
- if (co->co_name && PyString_Check(co->co_name))
- name = PyString_AS_STRING(co->co_name);
- PyOS_snprintf(buf, sizeof(buf),
- "<code object %.100s at %p, file \"%.300s\", line %d>",
- name, co, filename, lineno);
- return PyString_FromString(buf);
-}
-
-static int
-code_compare(PyCodeObject *co, PyCodeObject *cp)
-{
- int cmp;
- cmp = PyObject_Compare(co->co_name, cp->co_name);
- if (cmp) return cmp;
- cmp = co->co_argcount - cp->co_argcount;
- if (cmp) goto normalize;
- cmp = co->co_nlocals - cp->co_nlocals;
- if (cmp) goto normalize;
- cmp = co->co_flags - cp->co_flags;
- if (cmp) goto normalize;
- cmp = co->co_firstlineno - cp->co_firstlineno;
- if (cmp) goto normalize;
- cmp = PyObject_Compare(co->co_code, cp->co_code);
- if (cmp) return cmp;
- cmp = PyObject_Compare(co->co_consts, cp->co_consts);
- if (cmp) return cmp;
- cmp = PyObject_Compare(co->co_names, cp->co_names);
- if (cmp) return cmp;
- cmp = PyObject_Compare(co->co_varnames, cp->co_varnames);
- if (cmp) return cmp;
- cmp = PyObject_Compare(co->co_freevars, cp->co_freevars);
- if (cmp) return cmp;
- cmp = PyObject_Compare(co->co_cellvars, cp->co_cellvars);
- return cmp;
-
- normalize:
- if (cmp > 0)
- return 1;
- else if (cmp < 0)
- return -1;
- else
- return 0;
-}
-
-static long
-code_hash(PyCodeObject *co)
-{
- long h, h0, h1, h2, h3, h4, h5, h6;
- h0 = PyObject_Hash(co->co_name);
- if (h0 == -1) return -1;
- h1 = PyObject_Hash(co->co_code);
- if (h1 == -1) return -1;
- h2 = PyObject_Hash(co->co_consts);
- if (h2 == -1) return -1;
- h3 = PyObject_Hash(co->co_names);
- if (h3 == -1) return -1;
- h4 = PyObject_Hash(co->co_varnames);
- if (h4 == -1) return -1;
- h5 = PyObject_Hash(co->co_freevars);
- if (h5 == -1) return -1;
- h6 = PyObject_Hash(co->co_cellvars);
- if (h6 == -1) return -1;
- h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
- co->co_argcount ^ co->co_nlocals ^ co->co_flags;
- if (h == -1) h = -2;
- return h;
-}
-
-/* XXX code objects need to participate in GC? */
-
-PyTypeObject PyCode_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "code",
- sizeof(PyCodeObject),
- 0,
- (destructor)code_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)code_compare, /* tp_compare */
- (reprfunc)code_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)code_hash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- code_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- code_memberlist, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- code_new, /* tp_new */
-};
-
-/* All about c_lnotab.
-
-c_lnotab is an array of unsigned bytes disguised as a Python string. In -O
-mode, SET_LINENO opcodes aren't generated, and bytecode offsets are mapped
-to source code line #s (when needed for tracebacks) via c_lnotab instead.
-The array is conceptually a list of
- (bytecode offset increment, line number increment)
-pairs. The details are important and delicate, best illustrated by example:
-
- byte code offset source code line number
- 0 1
- 6 2
- 50 7
- 350 307
- 361 308
-
-The first trick is that these numbers aren't stored, only the increments
-from one row to the next (this doesn't really work, but it's a start):
-
- 0, 1, 6, 1, 44, 5, 300, 300, 11, 1
-
-The second trick is that an unsigned byte can't hold negative values, or
-values larger than 255, so (a) there's a deep assumption that byte code
-offsets and their corresponding line #s both increase monotonically, and (b)
-if at least one column jumps by more than 255 from one row to the next, more
-than one pair is written to the table. In case #b, there's no way to know
-from looking at the table later how many were written. That's the delicate
-part. A user of c_lnotab desiring to find the source line number
-corresponding to a bytecode address A should do something like this
-
- lineno = addr = 0
- for addr_incr, line_incr in c_lnotab:
- addr += addr_incr
- if addr > A:
- return lineno
- lineno += line_incr
-
-In order for this to work, when the addr field increments by more than 255,
-the line # increment in each pair generated must be 0 until the remaining addr
-increment is < 256. So, in the example above, com_set_lineno should not (as
-was actually done until 2.2) expand 300, 300 to 255, 255, 45, 45, but to
-255, 0, 45, 255, 0, 45.
-*/
-
-int
-PyCode_Addr2Line(PyCodeObject *co, int addrq)
-{
- int size = PyString_Size(co->co_lnotab) / 2;
- unsigned char *p = (unsigned char*)PyString_AsString(co->co_lnotab);
- int line = co->co_firstlineno;
- int addr = 0;
- while (--size >= 0) {
- addr += *p++;
- if (addr > addrq)
- break;
- line += *p++;
- }
- return line;
-}
-
-/*
- Check whether the current instruction is at the start of a line.
-
- */
-
- /* The theory of SET_LINENO-less tracing.
-
- In a nutshell, we use the co_lnotab field of the code object
- to tell when execution has moved onto a different line.
-
- As mentioned above, the basic idea is so set things up so
- that
-
- *instr_lb <= frame->f_lasti < *instr_ub
-
- is true so long as execution does not change lines.
-
- This is all fairly simple. Digging the information out of
- co_lnotab takes some work, but is conceptually clear.
-
- Somewhat harder to explain is why we don't *always* call the
- line trace function when the above test fails.
-
- Consider this code:
-
- 1: def f(a):
- 2: if a:
- 3: print 1
- 4: else:
- 5: print 2
-
- which compiles to this:
-
- 2 0 LOAD_FAST 0 (a)
- 3 JUMP_IF_FALSE 9 (to 15)
- 6 POP_TOP
-
- 3 7 LOAD_CONST 1 (1)
- 10 PRINT_ITEM
- 11 PRINT_NEWLINE
- 12 JUMP_FORWARD 6 (to 21)
- >> 15 POP_TOP
-
- 5 16 LOAD_CONST 2 (2)
- 19 PRINT_ITEM
- 20 PRINT_NEWLINE
- >> 21 LOAD_CONST 0 (None)
- 24 RETURN_VALUE
-
- If 'a' is false, execution will jump to instruction at offset
- 15 and the co_lnotab will claim that execution has moved to
- line 3. This is at best misleading. In this case we could
- associate the POP_TOP with line 4, but that doesn't make
- sense in all cases (I think).
-
- What we do is only call the line trace function if the co_lnotab
- indicates we have jumped to the *start* of a line, i.e. if the
- current instruction offset matches the offset given for the
- start of a line by the co_lnotab.
-
- This also takes care of the situation where 'a' is true.
- Execution will jump from instruction offset 12 to offset 21.
- Then the co_lnotab would imply that execution has moved to line
- 5, which is again misleading.
-
- Why do we set f_lineno when tracing? Well, consider the code
- above when 'a' is true. If stepping through this with 'n' in
- pdb, you would stop at line 1 with a "call" type event, then
- line events on lines 2 and 3, then a "return" type event -- but
- you would be shown line 5 during this event. This is a change
- from the behaviour in 2.2 and before, and I've found it
- confusing in practice. By setting and using f_lineno when
- tracing, one can report a line number different from that
- suggested by f_lasti on this one occasion where it's desirable.
- */
-
-
-int
-PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
-{
- int size, addr, line;
- unsigned char* p;
-
- p = (unsigned char*)PyString_AS_STRING(co->co_lnotab);
- size = PyString_GET_SIZE(co->co_lnotab) / 2;
-
- addr = 0;
- line = co->co_firstlineno;
- assert(line > 0);
-
- /* possible optimization: if f->f_lasti == instr_ub
- (likely to be a common case) then we already know
- instr_lb -- if we stored the matching value of p
- somwhere we could skip the first while loop. */
-
- /* see comments in compile.c for the description of
- co_lnotab. A point to remember: increments to p
- should come in pairs -- although we don't care about
- the line increments here, treating them as byte
- increments gets confusing, to say the least. */
-
- bounds->ap_lower = 0;
- while (size > 0) {
- if (addr + *p > lasti)
- break;
- addr += *p++;
- if (*p)
- bounds->ap_lower = addr;
- line += *p++;
- --size;
- }
-
- /* If lasti and addr don't match exactly, we don't want to
- change the lineno slot on the frame or execute a trace
- function. Return -1 instead.
- */
- if (addr != lasti)
- line = -1;
-
- if (size > 0) {
- while (--size >= 0) {
- addr += *p++;
- if (*p++)
- break;
- }
- bounds->ap_upper = addr;
- }
- else {
- bounds->ap_upper = INT_MAX;
- }
-
- return line;
-}
diff --git a/sys/src/cmd/python/Objects/complexobject.c b/sys/src/cmd/python/Objects/complexobject.c
deleted file mode 100644
index 4de1fb658..000000000
--- a/sys/src/cmd/python/Objects/complexobject.c
+++ /dev/null
@@ -1,1031 +0,0 @@
-
-/* Complex object implementation */
-
-/* Borrows heavily from floatobject.c */
-
-/* Submitted by Jim Hugunin */
-
-#include "Python.h"
-#include "structmember.h"
-
-#ifndef WITHOUT_COMPLEX
-
-/* Precisions used by repr() and str(), respectively.
-
- The repr() precision (17 significant decimal digits) is the minimal number
- that is guaranteed to have enough precision so that if the number is read
- back in the exact same binary value is recreated. This is true for IEEE
- floating point by design, and also happens to work for all other modern
- hardware.
-
- The str() precision is chosen so that in most cases, the rounding noise
- created by various operations is suppressed, while giving plenty of
- precision for practical use.
-*/
-
-#define PREC_REPR 17
-#define PREC_STR 12
-
-/* elementary operations on complex numbers */
-
-static Py_complex c_1 = {1., 0.};
-
-Py_complex
-c_sum(Py_complex a, Py_complex b)
-{
- Py_complex r;
- r.real = a.real + b.real;
- r.imag = a.imag + b.imag;
- return r;
-}
-
-Py_complex
-c_diff(Py_complex a, Py_complex b)
-{
- Py_complex r;
- r.real = a.real - b.real;
- r.imag = a.imag - b.imag;
- return r;
-}
-
-Py_complex
-c_neg(Py_complex a)
-{
- Py_complex r;
- r.real = -a.real;
- r.imag = -a.imag;
- return r;
-}
-
-Py_complex
-c_prod(Py_complex a, Py_complex b)
-{
- Py_complex r;
- r.real = a.real*b.real - a.imag*b.imag;
- r.imag = a.real*b.imag + a.imag*b.real;
- return r;
-}
-
-Py_complex
-c_quot(Py_complex a, Py_complex b)
-{
- /******************************************************************
- This was the original algorithm. It's grossly prone to spurious
- overflow and underflow errors. It also merrily divides by 0 despite
- checking for that(!). The code still serves a doc purpose here, as
- the algorithm following is a simple by-cases transformation of this
- one:
-
- Py_complex r;
- double d = b.real*b.real + b.imag*b.imag;
- if (d == 0.)
- errno = EDOM;
- r.real = (a.real*b.real + a.imag*b.imag)/d;
- r.imag = (a.imag*b.real - a.real*b.imag)/d;
- return r;
- ******************************************************************/
-
- /* This algorithm is better, and is pretty obvious: first divide the
- * numerators and denominator by whichever of {b.real, b.imag} has
- * larger magnitude. The earliest reference I found was to CACM
- * Algorithm 116 (Complex Division, Robert L. Smith, Stanford
- * University). As usual, though, we're still ignoring all IEEE
- * endcases.
- */
- Py_complex r; /* the result */
- const double abs_breal = b.real < 0 ? -b.real : b.real;
- const double abs_bimag = b.imag < 0 ? -b.imag : b.imag;
-
- if (abs_breal >= abs_bimag) {
- /* divide tops and bottom by b.real */
- if (abs_breal == 0.0) {
- errno = EDOM;
- r.real = r.imag = 0.0;
- }
- else {
- const double ratio = b.imag / b.real;
- const double denom = b.real + b.imag * ratio;
- r.real = (a.real + a.imag * ratio) / denom;
- r.imag = (a.imag - a.real * ratio) / denom;
- }
- }
- else {
- /* divide tops and bottom by b.imag */
- const double ratio = b.real / b.imag;
- const double denom = b.real * ratio + b.imag;
- assert(b.imag != 0.0);
- r.real = (a.real * ratio + a.imag) / denom;
- r.imag = (a.imag * ratio - a.real) / denom;
- }
- return r;
-}
-
-Py_complex
-c_pow(Py_complex a, Py_complex b)
-{
- Py_complex r;
- double vabs,len,at,phase;
- if (b.real == 0. && b.imag == 0.) {
- r.real = 1.;
- r.imag = 0.;
- }
- else if (a.real == 0. && a.imag == 0.) {
- if (b.imag != 0. || b.real < 0.)
- errno = EDOM;
- r.real = 0.;
- r.imag = 0.;
- }
- else {
- vabs = hypot(a.real,a.imag);
- len = pow(vabs,b.real);
- at = atan2(a.imag, a.real);
- phase = at*b.real;
- if (b.imag != 0.0) {
- len /= exp(at*b.imag);
- phase += b.imag*log(vabs);
- }
- r.real = len*cos(phase);
- r.imag = len*sin(phase);
- }
- return r;
-}
-
-static Py_complex
-c_powu(Py_complex x, long n)
-{
- Py_complex r, p;
- long mask = 1;
- r = c_1;
- p = x;
- while (mask > 0 && n >= mask) {
- if (n & mask)
- r = c_prod(r,p);
- mask <<= 1;
- p = c_prod(p,p);
- }
- return r;
-}
-
-static Py_complex
-c_powi(Py_complex x, long n)
-{
- Py_complex cn;
-
- if (n > 100 || n < -100) {
- cn.real = (double) n;
- cn.imag = 0.;
- return c_pow(x,cn);
- }
- else if (n > 0)
- return c_powu(x,n);
- else
- return c_quot(c_1,c_powu(x,-n));
-
-}
-
-static PyObject *
-complex_subtype_from_c_complex(PyTypeObject *type, Py_complex cval)
-{
- PyObject *op;
-
- op = type->tp_alloc(type, 0);
- if (op != NULL)
- ((PyComplexObject *)op)->cval = cval;
- return op;
-}
-
-PyObject *
-PyComplex_FromCComplex(Py_complex cval)
-{
- register PyComplexObject *op;
-
- /* Inline PyObject_New */
- op = (PyComplexObject *) PyObject_MALLOC(sizeof(PyComplexObject));
- if (op == NULL)
- return PyErr_NoMemory();
- PyObject_INIT(op, &PyComplex_Type);
- op->cval = cval;
- return (PyObject *) op;
-}
-
-static PyObject *
-complex_subtype_from_doubles(PyTypeObject *type, double real, double imag)
-{
- Py_complex c;
- c.real = real;
- c.imag = imag;
- return complex_subtype_from_c_complex(type, c);
-}
-
-PyObject *
-PyComplex_FromDoubles(double real, double imag)
-{
- Py_complex c;
- c.real = real;
- c.imag = imag;
- return PyComplex_FromCComplex(c);
-}
-
-double
-PyComplex_RealAsDouble(PyObject *op)
-{
- if (PyComplex_Check(op)) {
- return ((PyComplexObject *)op)->cval.real;
- }
- else {
- return PyFloat_AsDouble(op);
- }
-}
-
-double
-PyComplex_ImagAsDouble(PyObject *op)
-{
- if (PyComplex_Check(op)) {
- return ((PyComplexObject *)op)->cval.imag;
- }
- else {
- return 0.0;
- }
-}
-
-Py_complex
-PyComplex_AsCComplex(PyObject *op)
-{
- Py_complex cv;
- if (PyComplex_Check(op)) {
- return ((PyComplexObject *)op)->cval;
- }
- else {
- cv.real = PyFloat_AsDouble(op);
- cv.imag = 0.;
- return cv;
- }
-}
-
-static void
-complex_dealloc(PyObject *op)
-{
- op->ob_type->tp_free(op);
-}
-
-
-static void
-complex_to_buf(char *buf, int bufsz, PyComplexObject *v, int precision)
-{
- char format[32];
- if (v->cval.real == 0.) {
- PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
- PyOS_ascii_formatd(buf, bufsz - 1, format, v->cval.imag);
- strncat(buf, "j", 1);
- } else {
- char re[64], im[64];
- /* Format imaginary part with sign, real part without */
- PyOS_snprintf(format, sizeof(format), "%%.%ig", precision);
- PyOS_ascii_formatd(re, sizeof(re), format, v->cval.real);
- PyOS_snprintf(format, sizeof(format), "%%+.%ig", precision);
- PyOS_ascii_formatd(im, sizeof(im), format, v->cval.imag);
- PyOS_snprintf(buf, bufsz, "(%s%sj)", re, im);
- }
-}
-
-static int
-complex_print(PyComplexObject *v, FILE *fp, int flags)
-{
- char buf[100];
- complex_to_buf(buf, sizeof(buf), v,
- (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
- fputs(buf, fp);
- return 0;
-}
-
-static PyObject *
-complex_repr(PyComplexObject *v)
-{
- char buf[100];
- complex_to_buf(buf, sizeof(buf), v, PREC_REPR);
- return PyString_FromString(buf);
-}
-
-static PyObject *
-complex_str(PyComplexObject *v)
-{
- char buf[100];
- complex_to_buf(buf, sizeof(buf), v, PREC_STR);
- return PyString_FromString(buf);
-}
-
-static long
-complex_hash(PyComplexObject *v)
-{
- long hashreal, hashimag, combined;
- hashreal = _Py_HashDouble(v->cval.real);
- if (hashreal == -1)
- return -1;
- hashimag = _Py_HashDouble(v->cval.imag);
- if (hashimag == -1)
- return -1;
- /* Note: if the imaginary part is 0, hashimag is 0 now,
- * so the following returns hashreal unchanged. This is
- * important because numbers of different types that
- * compare equal must have the same hash value, so that
- * hash(x + 0*j) must equal hash(x).
- */
- combined = hashreal + 1000003 * hashimag;
- if (combined == -1)
- combined = -2;
- return combined;
-}
-
-static PyObject *
-complex_add(PyComplexObject *v, PyComplexObject *w)
-{
- Py_complex result;
- PyFPE_START_PROTECT("complex_add", return 0)
- result = c_sum(v->cval,w->cval);
- PyFPE_END_PROTECT(result)
- return PyComplex_FromCComplex(result);
-}
-
-static PyObject *
-complex_sub(PyComplexObject *v, PyComplexObject *w)
-{
- Py_complex result;
- PyFPE_START_PROTECT("complex_sub", return 0)
- result = c_diff(v->cval,w->cval);
- PyFPE_END_PROTECT(result)
- return PyComplex_FromCComplex(result);
-}
-
-static PyObject *
-complex_mul(PyComplexObject *v, PyComplexObject *w)
-{
- Py_complex result;
- PyFPE_START_PROTECT("complex_mul", return 0)
- result = c_prod(v->cval,w->cval);
- PyFPE_END_PROTECT(result)
- return PyComplex_FromCComplex(result);
-}
-
-static PyObject *
-complex_div(PyComplexObject *v, PyComplexObject *w)
-{
- Py_complex quot;
- PyFPE_START_PROTECT("complex_div", return 0)
- errno = 0;
- quot = c_quot(v->cval,w->cval);
- PyFPE_END_PROTECT(quot)
- if (errno == EDOM) {
- PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
- return NULL;
- }
- return PyComplex_FromCComplex(quot);
-}
-
-static PyObject *
-complex_classic_div(PyComplexObject *v, PyComplexObject *w)
-{
- Py_complex quot;
-
- if (Py_DivisionWarningFlag >= 2 &&
- PyErr_Warn(PyExc_DeprecationWarning,
- "classic complex division") < 0)
- return NULL;
-
- PyFPE_START_PROTECT("complex_classic_div", return 0)
- errno = 0;
- quot = c_quot(v->cval,w->cval);
- PyFPE_END_PROTECT(quot)
- if (errno == EDOM) {
- PyErr_SetString(PyExc_ZeroDivisionError, "complex division");
- return NULL;
- }
- return PyComplex_FromCComplex(quot);
-}
-
-static PyObject *
-complex_remainder(PyComplexObject *v, PyComplexObject *w)
-{
- Py_complex div, mod;
-
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "complex divmod(), // and % are deprecated") < 0)
- return NULL;
-
- errno = 0;
- div = c_quot(v->cval,w->cval); /* The raw divisor value. */
- if (errno == EDOM) {
- PyErr_SetString(PyExc_ZeroDivisionError, "complex remainder");
- return NULL;
- }
- div.real = floor(div.real); /* Use the floor of the real part. */
- div.imag = 0.0;
- mod = c_diff(v->cval, c_prod(w->cval, div));
-
- return PyComplex_FromCComplex(mod);
-}
-
-
-static PyObject *
-complex_divmod(PyComplexObject *v, PyComplexObject *w)
-{
- Py_complex div, mod;
- PyObject *d, *m, *z;
-
- if (PyErr_Warn(PyExc_DeprecationWarning,
- "complex divmod(), // and % are deprecated") < 0)
- return NULL;
-
- errno = 0;
- div = c_quot(v->cval,w->cval); /* The raw divisor value. */
- if (errno == EDOM) {
- PyErr_SetString(PyExc_ZeroDivisionError, "complex divmod()");
- return NULL;
- }
- div.real = floor(div.real); /* Use the floor of the real part. */
- div.imag = 0.0;
- mod = c_diff(v->cval, c_prod(w->cval, div));
- d = PyComplex_FromCComplex(div);
- m = PyComplex_FromCComplex(mod);
- z = PyTuple_Pack(2, d, m);
- Py_XDECREF(d);
- Py_XDECREF(m);
- return z;
-}
-
-static PyObject *
-complex_pow(PyComplexObject *v, PyObject *w, PyComplexObject *z)
-{
- Py_complex p;
- Py_complex exponent;
- long int_exponent;
-
- if ((PyObject *)z!=Py_None) {
- PyErr_SetString(PyExc_ValueError, "complex modulo");
- return NULL;
- }
- PyFPE_START_PROTECT("complex_pow", return 0)
- errno = 0;
- exponent = ((PyComplexObject*)w)->cval;
- int_exponent = (long)exponent.real;
- if (exponent.imag == 0. && exponent.real == int_exponent)
- p = c_powi(v->cval,int_exponent);
- else
- p = c_pow(v->cval,exponent);
-
- PyFPE_END_PROTECT(p)
- Py_ADJUST_ERANGE2(p.real, p.imag);
- if (errno == EDOM) {
- PyErr_SetString(PyExc_ZeroDivisionError,
- "0.0 to a negative or complex power");
- return NULL;
- }
- else if (errno == ERANGE) {
- PyErr_SetString(PyExc_OverflowError,
- "complex exponentiation");
- return NULL;
- }
- return PyComplex_FromCComplex(p);
-}
-
-static PyObject *
-complex_int_div(PyComplexObject *v, PyComplexObject *w)
-{
- PyObject *t, *r;
-
- t = complex_divmod(v, w);
- if (t != NULL) {
- r = PyTuple_GET_ITEM(t, 0);
- Py_INCREF(r);
- Py_DECREF(t);
- return r;
- }
- return NULL;
-}
-
-static PyObject *
-complex_neg(PyComplexObject *v)
-{
- Py_complex neg;
- neg.real = -v->cval.real;
- neg.imag = -v->cval.imag;
- return PyComplex_FromCComplex(neg);
-}
-
-static PyObject *
-complex_pos(PyComplexObject *v)
-{
- if (PyComplex_CheckExact(v)) {
- Py_INCREF(v);
- return (PyObject *)v;
- }
- else
- return PyComplex_FromCComplex(v->cval);
-}
-
-static PyObject *
-complex_abs(PyComplexObject *v)
-{
- double result;
- PyFPE_START_PROTECT("complex_abs", return 0)
- result = hypot(v->cval.real,v->cval.imag);
- PyFPE_END_PROTECT(result)
- return PyFloat_FromDouble(result);
-}
-
-static int
-complex_nonzero(PyComplexObject *v)
-{
- return v->cval.real != 0.0 || v->cval.imag != 0.0;
-}
-
-static int
-complex_coerce(PyObject **pv, PyObject **pw)
-{
- Py_complex cval;
- cval.imag = 0.;
- if (PyInt_Check(*pw)) {
- cval.real = (double)PyInt_AsLong(*pw);
- *pw = PyComplex_FromCComplex(cval);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyLong_Check(*pw)) {
- cval.real = PyLong_AsDouble(*pw);
- if (cval.real == -1.0 && PyErr_Occurred())
- return -1;
- *pw = PyComplex_FromCComplex(cval);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyFloat_Check(*pw)) {
- cval.real = PyFloat_AsDouble(*pw);
- *pw = PyComplex_FromCComplex(cval);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyComplex_Check(*pw)) {
- Py_INCREF(*pv);
- Py_INCREF(*pw);
- return 0;
- }
- return 1; /* Can't do it */
-}
-
-static PyObject *
-complex_richcompare(PyObject *v, PyObject *w, int op)
-{
- int c;
- Py_complex i, j;
- PyObject *res;
-
- c = PyNumber_CoerceEx(&v, &w);
- if (c < 0)
- return NULL;
- if (c > 0) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- /* Make sure both arguments are complex. */
- if (!(PyComplex_Check(v) && PyComplex_Check(w))) {
- Py_DECREF(v);
- Py_DECREF(w);
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- i = ((PyComplexObject *)v)->cval;
- j = ((PyComplexObject *)w)->cval;
- Py_DECREF(v);
- Py_DECREF(w);
-
- if (op != Py_EQ && op != Py_NE) {
- PyErr_SetString(PyExc_TypeError,
- "no ordering relation is defined for complex numbers");
- return NULL;
- }
-
- if ((i.real == j.real && i.imag == j.imag) == (op == Py_EQ))
- res = Py_True;
- else
- res = Py_False;
-
- Py_INCREF(res);
- return res;
-}
-
-static PyObject *
-complex_int(PyObject *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "can't convert complex to int; use int(abs(z))");
- return NULL;
-}
-
-static PyObject *
-complex_long(PyObject *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "can't convert complex to long; use long(abs(z))");
- return NULL;
-}
-
-static PyObject *
-complex_float(PyObject *v)
-{
- PyErr_SetString(PyExc_TypeError,
- "can't convert complex to float; use abs(z)");
- return NULL;
-}
-
-static PyObject *
-complex_conjugate(PyObject *self)
-{
- Py_complex c;
- c = ((PyComplexObject *)self)->cval;
- c.imag = -c.imag;
- return PyComplex_FromCComplex(c);
-}
-
-static PyObject *
-complex_getnewargs(PyComplexObject *v)
-{
- return Py_BuildValue("(D)", &v->cval);
-}
-
-static PyMethodDef complex_methods[] = {
- {"conjugate", (PyCFunction)complex_conjugate, METH_NOARGS},
- {"__getnewargs__", (PyCFunction)complex_getnewargs, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyMemberDef complex_members[] = {
- {"real", T_DOUBLE, offsetof(PyComplexObject, cval.real), READONLY,
- "the real part of a complex number"},
- {"imag", T_DOUBLE, offsetof(PyComplexObject, cval.imag), READONLY,
- "the imaginary part of a complex number"},
- {0},
-};
-
-static PyObject *
-complex_subtype_from_string(PyTypeObject *type, PyObject *v)
-{
- const char *s, *start;
- char *end;
- double x=0.0, y=0.0, z;
- int got_re=0, got_im=0, done=0;
- int digit_or_dot;
- int sw_error=0;
- int sign;
- char buffer[256]; /* For errors */
-#ifdef Py_USING_UNICODE
- char s_buffer[256];
-#endif
- Py_ssize_t len;
-
- if (PyString_Check(v)) {
- s = PyString_AS_STRING(v);
- len = PyString_GET_SIZE(v);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(v)) {
- if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) {
- PyErr_SetString(PyExc_ValueError,
- "complex() literal too large to convert");
- return NULL;
- }
- if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
- PyUnicode_GET_SIZE(v),
- s_buffer,
- NULL))
- return NULL;
- s = s_buffer;
- len = strlen(s);
- }
-#endif
- else if (PyObject_AsCharBuffer(v, &s, &len)) {
- PyErr_SetString(PyExc_TypeError,
- "complex() arg is not a string");
- return NULL;
- }
-
- /* position on first nonblank */
- start = s;
- while (*s && isspace(Py_CHARMASK(*s)))
- s++;
- if (s[0] == '\0') {
- PyErr_SetString(PyExc_ValueError,
- "complex() arg is an empty string");
- return NULL;
- }
-
- z = -1.0;
- sign = 1;
- do {
-
- switch (*s) {
-
- case '\0':
- if (s-start != len) {
- PyErr_SetString(
- PyExc_ValueError,
- "complex() arg contains a null byte");
- return NULL;
- }
- if(!done) sw_error=1;
- break;
-
- case '-':
- sign = -1;
- /* Fallthrough */
- case '+':
- if (done) sw_error=1;
- s++;
- if ( *s=='\0'||*s=='+'||*s=='-' ||
- isspace(Py_CHARMASK(*s)) ) sw_error=1;
- break;
-
- case 'J':
- case 'j':
- if (got_im || done) {
- sw_error = 1;
- break;
- }
- if (z<0.0) {
- y=sign;
- }
- else{
- y=sign*z;
- }
- got_im=1;
- s++;
- if (*s!='+' && *s!='-' )
- done=1;
- break;
-
- default:
- if (isspace(Py_CHARMASK(*s))) {
- while (*s && isspace(Py_CHARMASK(*s)))
- s++;
- if (s[0] != '\0')
- sw_error=1;
- else
- done = 1;
- break;
- }
- digit_or_dot =
- (*s=='.' || isdigit(Py_CHARMASK(*s)));
- if (done||!digit_or_dot) {
- sw_error=1;
- break;
- }
- errno = 0;
- PyFPE_START_PROTECT("strtod", return 0)
- z = PyOS_ascii_strtod(s, &end) ;
- PyFPE_END_PROTECT(z)
- if (errno != 0) {
- PyOS_snprintf(buffer, sizeof(buffer),
- "float() out of range: %.150s", s);
- PyErr_SetString(
- PyExc_ValueError,
- buffer);
- return NULL;
- }
- s=end;
- if (*s=='J' || *s=='j') {
-
- break;
- }
- if (got_re) {
- sw_error=1;
- break;
- }
-
- /* accept a real part */
- x=sign*z;
- got_re=1;
- if (got_im) done=1;
- z = -1.0;
- sign = 1;
- break;
-
- } /* end of switch */
-
- } while (s - start < len && !sw_error);
-
- if (sw_error) {
- PyErr_SetString(PyExc_ValueError,
- "complex() arg is a malformed string");
- return NULL;
- }
-
- return complex_subtype_from_doubles(type, x, y);
-}
-
-static PyObject *
-complex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *r, *i, *tmp, *f;
- PyNumberMethods *nbr, *nbi = NULL;
- Py_complex cr, ci;
- int own_r = 0;
- static PyObject *complexstr;
- static char *kwlist[] = {"real", "imag", 0};
-
- r = Py_False;
- i = NULL;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO:complex", kwlist,
- &r, &i))
- return NULL;
-
- /* Special-case for single argument that is already complex */
- if (PyComplex_CheckExact(r) && i == NULL &&
- type == &PyComplex_Type) {
- /* Note that we can't know whether it's safe to return
- a complex *subclass* instance as-is, hence the restriction
- to exact complexes here. */
- Py_INCREF(r);
- return r;
- }
- if (PyString_Check(r) || PyUnicode_Check(r)) {
- if (i != NULL) {
- PyErr_SetString(PyExc_TypeError,
- "complex() can't take second arg"
- " if first is a string");
- return NULL;
- }
- return complex_subtype_from_string(type, r);
- }
- if (i != NULL && (PyString_Check(i) || PyUnicode_Check(i))) {
- PyErr_SetString(PyExc_TypeError,
- "complex() second arg can't be a string");
- return NULL;
- }
-
- /* XXX Hack to support classes with __complex__ method */
- if (complexstr == NULL) {
- complexstr = PyString_InternFromString("__complex__");
- if (complexstr == NULL)
- return NULL;
- }
- f = PyObject_GetAttr(r, complexstr);
- if (f == NULL)
- PyErr_Clear();
- else {
- PyObject *args = PyTuple_New(0);
- if (args == NULL)
- return NULL;
- r = PyEval_CallObject(f, args);
- Py_DECREF(args);
- Py_DECREF(f);
- if (r == NULL)
- return NULL;
- own_r = 1;
- }
- nbr = r->ob_type->tp_as_number;
- if (i != NULL)
- nbi = i->ob_type->tp_as_number;
- if (nbr == NULL || nbr->nb_float == NULL ||
- ((i != NULL) && (nbi == NULL || nbi->nb_float == NULL))) {
- PyErr_SetString(PyExc_TypeError,
- "complex() argument must be a string or a number");
- if (own_r) {
- Py_DECREF(r);
- }
- return NULL;
- }
- if (PyComplex_Check(r)) {
- /* Note that if r is of a complex subtype, we're only
- retaining its real & imag parts here, and the return
- value is (properly) of the builtin complex type. */
- cr = ((PyComplexObject*)r)->cval;
- if (own_r) {
- Py_DECREF(r);
- }
- }
- else {
- tmp = PyNumber_Float(r);
- if (own_r) {
- Py_DECREF(r);
- }
- if (tmp == NULL)
- return NULL;
- if (!PyFloat_Check(tmp)) {
- PyErr_SetString(PyExc_TypeError,
- "float(r) didn't return a float");
- Py_DECREF(tmp);
- return NULL;
- }
- cr.real = PyFloat_AsDouble(tmp);
- Py_DECREF(tmp);
- cr.imag = 0.0;
- }
- if (i == NULL) {
- ci.real = 0.0;
- ci.imag = 0.0;
- }
- else if (PyComplex_Check(i))
- ci = ((PyComplexObject*)i)->cval;
- else {
- tmp = (*nbi->nb_float)(i);
- if (tmp == NULL)
- return NULL;
- ci.real = PyFloat_AsDouble(tmp);
- Py_DECREF(tmp);
- ci.imag = 0.;
- }
- cr.real -= ci.imag;
- cr.imag += ci.real;
- return complex_subtype_from_c_complex(type, cr);
-}
-
-PyDoc_STRVAR(complex_doc,
-"complex(real[, imag]) -> complex number\n"
-"\n"
-"Create a complex number from a real part and an optional imaginary part.\n"
-"This is equivalent to (real + imag*1j) where imag defaults to 0.");
-
-static PyNumberMethods complex_as_number = {
- (binaryfunc)complex_add, /* nb_add */
- (binaryfunc)complex_sub, /* nb_subtract */
- (binaryfunc)complex_mul, /* nb_multiply */
- (binaryfunc)complex_classic_div, /* nb_divide */
- (binaryfunc)complex_remainder, /* nb_remainder */
- (binaryfunc)complex_divmod, /* nb_divmod */
- (ternaryfunc)complex_pow, /* nb_power */
- (unaryfunc)complex_neg, /* nb_negative */
- (unaryfunc)complex_pos, /* nb_positive */
- (unaryfunc)complex_abs, /* nb_absolute */
- (inquiry)complex_nonzero, /* nb_nonzero */
- 0, /* nb_invert */
- 0, /* nb_lshift */
- 0, /* nb_rshift */
- 0, /* nb_and */
- 0, /* nb_xor */
- 0, /* nb_or */
- complex_coerce, /* nb_coerce */
- complex_int, /* nb_int */
- complex_long, /* nb_long */
- complex_float, /* nb_float */
- 0, /* nb_oct */
- 0, /* nb_hex */
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply*/
- 0, /* nb_inplace_divide */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- (binaryfunc)complex_int_div, /* nb_floor_divide */
- (binaryfunc)complex_div, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
-};
-
-PyTypeObject PyComplex_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "complex",
- sizeof(PyComplexObject),
- 0,
- complex_dealloc, /* tp_dealloc */
- (printfunc)complex_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)complex_repr, /* tp_repr */
- &complex_as_number, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)complex_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)complex_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- complex_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- complex_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- complex_methods, /* tp_methods */
- complex_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- complex_new, /* tp_new */
- PyObject_Del, /* tp_free */
-};
-
-#endif
diff --git a/sys/src/cmd/python/Objects/descrobject.c b/sys/src/cmd/python/Objects/descrobject.c
deleted file mode 100644
index 914b6d35a..000000000
--- a/sys/src/cmd/python/Objects/descrobject.c
+++ /dev/null
@@ -1,1283 +0,0 @@
-/* Descriptors -- a new, flexible way to describe attributes */
-
-#include "Python.h"
-#include "structmember.h" /* Why is this not included in Python.h? */
-
-static void
-descr_dealloc(PyDescrObject *descr)
-{
- _PyObject_GC_UNTRACK(descr);
- Py_XDECREF(descr->d_type);
- Py_XDECREF(descr->d_name);
- PyObject_GC_Del(descr);
-}
-
-static char *
-descr_name(PyDescrObject *descr)
-{
- if (descr->d_name != NULL && PyString_Check(descr->d_name))
- return PyString_AS_STRING(descr->d_name);
- else
- return "?";
-}
-
-static PyObject *
-descr_repr(PyDescrObject *descr, char *format)
-{
- return PyString_FromFormat(format, descr_name(descr),
- descr->d_type->tp_name);
-}
-
-static PyObject *
-method_repr(PyMethodDescrObject *descr)
-{
- return descr_repr((PyDescrObject *)descr,
- "<method '%s' of '%s' objects>");
-}
-
-static PyObject *
-member_repr(PyMemberDescrObject *descr)
-{
- return descr_repr((PyDescrObject *)descr,
- "<member '%s' of '%s' objects>");
-}
-
-static PyObject *
-getset_repr(PyGetSetDescrObject *descr)
-{
- return descr_repr((PyDescrObject *)descr,
- "<attribute '%s' of '%s' objects>");
-}
-
-static PyObject *
-wrapperdescr_repr(PyWrapperDescrObject *descr)
-{
- return descr_repr((PyDescrObject *)descr,
- "<slot wrapper '%s' of '%s' objects>");
-}
-
-static int
-descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
-{
- if (obj == NULL) {
- Py_INCREF(descr);
- *pres = (PyObject *)descr;
- return 1;
- }
- if (!PyObject_TypeCheck(obj, descr->d_type)) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%s' for '%s' objects "
- "doesn't apply to '%s' object",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name,
- obj->ob_type->tp_name);
- *pres = NULL;
- return 1;
- }
- return 0;
-}
-
-static PyObject *
-classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
-{
- /* Ensure a valid type. Class methods ignore obj. */
- if (type == NULL) {
- if (obj != NULL)
- type = (PyObject *)obj->ob_type;
- else {
- /* Wot - no type?! */
- PyErr_Format(PyExc_TypeError,
- "descriptor '%s' for type '%s' "
- "needs either an object or a type",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name);
- return NULL;
- }
- }
- if (!PyType_Check(type)) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%s' for type '%s' "
- "needs a type, not a '%s' as arg 2",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name,
- type->ob_type->tp_name);
- return NULL;
- }
- if (!PyType_IsSubtype((PyTypeObject *)type, descr->d_type)) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%s' for type '%s' "
- "doesn't apply to type '%s'",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name,
- ((PyTypeObject *)type)->tp_name);
- return NULL;
- }
- return PyCFunction_New(descr->d_method, type);
-}
-
-static PyObject *
-method_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
-{
- PyObject *res;
-
- if (descr_check((PyDescrObject *)descr, obj, &res))
- return res;
- return PyCFunction_New(descr->d_method, obj);
-}
-
-static PyObject *
-member_get(PyMemberDescrObject *descr, PyObject *obj, PyObject *type)
-{
- PyObject *res;
-
- if (descr_check((PyDescrObject *)descr, obj, &res))
- return res;
- return PyMember_GetOne((char *)obj, descr->d_member);
-}
-
-static PyObject *
-getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
-{
- PyObject *res;
-
- if (descr_check((PyDescrObject *)descr, obj, &res))
- return res;
- if (descr->d_getset->get != NULL)
- return descr->d_getset->get(obj, descr->d_getset->closure);
- PyErr_Format(PyExc_AttributeError,
- "attribute '%.300s' of '%.100s' objects is not readable",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name);
- return NULL;
-}
-
-static PyObject *
-wrapperdescr_get(PyWrapperDescrObject *descr, PyObject *obj, PyObject *type)
-{
- PyObject *res;
-
- if (descr_check((PyDescrObject *)descr, obj, &res))
- return res;
- return PyWrapper_New((PyObject *)descr, obj);
-}
-
-static int
-descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
- int *pres)
-{
- assert(obj != NULL);
- if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%.200s' for '%.100s' objects "
- "doesn't apply to '%.100s' object",
- descr_name(descr),
- descr->d_type->tp_name,
- obj->ob_type->tp_name);
- *pres = -1;
- return 1;
- }
- return 0;
-}
-
-static int
-member_set(PyMemberDescrObject *descr, PyObject *obj, PyObject *value)
-{
- int res;
-
- if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
- return res;
- return PyMember_SetOne((char *)obj, descr->d_member, value);
-}
-
-static int
-getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
-{
- int res;
-
- if (descr_setcheck((PyDescrObject *)descr, obj, value, &res))
- return res;
- if (descr->d_getset->set != NULL)
- return descr->d_getset->set(obj, value,
- descr->d_getset->closure);
- PyErr_Format(PyExc_AttributeError,
- "attribute '%.300s' of '%.100s' objects is not writable",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name);
- return -1;
-}
-
-static PyObject *
-methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
-{
- Py_ssize_t argc;
- PyObject *self, *func, *result;
-
- /* Make sure that the first argument is acceptable as 'self' */
- assert(PyTuple_Check(args));
- argc = PyTuple_GET_SIZE(args);
- if (argc < 1) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%.300s' of '%.100s' "
- "object needs an argument",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name);
- return NULL;
- }
- self = PyTuple_GET_ITEM(args, 0);
- if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%.200s' "
- "requires a '%.100s' object "
- "but received a '%.100s'",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name,
- self->ob_type->tp_name);
- return NULL;
- }
-
- func = PyCFunction_New(descr->d_method, self);
- if (func == NULL)
- return NULL;
- args = PyTuple_GetSlice(args, 1, argc);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObjectWithKeywords(func, args, kwds);
- Py_DECREF(args);
- Py_DECREF(func);
- return result;
-}
-
-static PyObject *
-classmethoddescr_call(PyMethodDescrObject *descr, PyObject *args,
- PyObject *kwds)
-{
- PyObject *func, *result;
-
- func = PyCFunction_New(descr->d_method, (PyObject *)descr->d_type);
- if (func == NULL)
- return NULL;
-
- result = PyEval_CallObjectWithKeywords(func, args, kwds);
- Py_DECREF(func);
- return result;
-}
-
-static PyObject *
-wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
-{
- Py_ssize_t argc;
- PyObject *self, *func, *result;
-
- /* Make sure that the first argument is acceptable as 'self' */
- assert(PyTuple_Check(args));
- argc = PyTuple_GET_SIZE(args);
- if (argc < 1) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%.300s' of '%.100s' "
- "object needs an argument",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name);
- return NULL;
- }
- self = PyTuple_GET_ITEM(args, 0);
- if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
- PyErr_Format(PyExc_TypeError,
- "descriptor '%.200s' "
- "requires a '%.100s' object "
- "but received a '%.100s'",
- descr_name((PyDescrObject *)descr),
- descr->d_type->tp_name,
- self->ob_type->tp_name);
- return NULL;
- }
-
- func = PyWrapper_New((PyObject *)descr, self);
- if (func == NULL)
- return NULL;
- args = PyTuple_GetSlice(args, 1, argc);
- if (args == NULL) {
- Py_DECREF(func);
- return NULL;
- }
- result = PyEval_CallObjectWithKeywords(func, args, kwds);
- Py_DECREF(args);
- Py_DECREF(func);
- return result;
-}
-
-static PyObject *
-method_get_doc(PyMethodDescrObject *descr, void *closure)
-{
- if (descr->d_method->ml_doc == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyString_FromString(descr->d_method->ml_doc);
-}
-
-static PyMemberDef descr_members[] = {
- {"__objclass__", T_OBJECT, offsetof(PyDescrObject, d_type), READONLY},
- {"__name__", T_OBJECT, offsetof(PyDescrObject, d_name), READONLY},
- {0}
-};
-
-static PyGetSetDef method_getset[] = {
- {"__doc__", (getter)method_get_doc},
- {0}
-};
-
-static PyObject *
-member_get_doc(PyMemberDescrObject *descr, void *closure)
-{
- if (descr->d_member->doc == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyString_FromString(descr->d_member->doc);
-}
-
-static PyGetSetDef member_getset[] = {
- {"__doc__", (getter)member_get_doc},
- {0}
-};
-
-static PyObject *
-getset_get_doc(PyGetSetDescrObject *descr, void *closure)
-{
- if (descr->d_getset->doc == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyString_FromString(descr->d_getset->doc);
-}
-
-static PyGetSetDef getset_getset[] = {
- {"__doc__", (getter)getset_get_doc},
- {0}
-};
-
-static PyObject *
-wrapperdescr_get_doc(PyWrapperDescrObject *descr, void *closure)
-{
- if (descr->d_base->doc == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyString_FromString(descr->d_base->doc);
-}
-
-static PyGetSetDef wrapperdescr_getset[] = {
- {"__doc__", (getter)wrapperdescr_get_doc},
- {0}
-};
-
-static int
-descr_traverse(PyObject *self, visitproc visit, void *arg)
-{
- PyDescrObject *descr = (PyDescrObject *)self;
- Py_VISIT(descr->d_type);
- return 0;
-}
-
-static PyTypeObject PyMethodDescr_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "method_descriptor",
- sizeof(PyMethodDescrObject),
- 0,
- (destructor)descr_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)method_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- (ternaryfunc)methoddescr_call, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- descr_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- descr_members, /* tp_members */
- method_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- (descrgetfunc)method_get, /* tp_descr_get */
- 0, /* tp_descr_set */
-};
-
-/* This is for METH_CLASS in C, not for "f = classmethod(f)" in Python! */
-static PyTypeObject PyClassMethodDescr_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "classmethod_descriptor",
- sizeof(PyMethodDescrObject),
- 0,
- (destructor)descr_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)method_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- (ternaryfunc)classmethoddescr_call, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- descr_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- descr_members, /* tp_members */
- method_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- (descrgetfunc)classmethod_get, /* tp_descr_get */
- 0, /* tp_descr_set */
-};
-
-static PyTypeObject PyMemberDescr_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "member_descriptor",
- sizeof(PyMemberDescrObject),
- 0,
- (destructor)descr_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)member_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- descr_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- descr_members, /* tp_members */
- member_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- (descrgetfunc)member_get, /* tp_descr_get */
- (descrsetfunc)member_set, /* tp_descr_set */
-};
-
-static PyTypeObject PyGetSetDescr_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "getset_descriptor",
- sizeof(PyGetSetDescrObject),
- 0,
- (destructor)descr_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)getset_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- descr_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- descr_members, /* tp_members */
- getset_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- (descrgetfunc)getset_get, /* tp_descr_get */
- (descrsetfunc)getset_set, /* tp_descr_set */
-};
-
-PyTypeObject PyWrapperDescr_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "wrapper_descriptor",
- sizeof(PyWrapperDescrObject),
- 0,
- (destructor)descr_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)wrapperdescr_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- (ternaryfunc)wrapperdescr_call, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- descr_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- descr_members, /* tp_members */
- wrapperdescr_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- (descrgetfunc)wrapperdescr_get, /* tp_descr_get */
- 0, /* tp_descr_set */
-};
-
-static PyDescrObject *
-descr_new(PyTypeObject *descrtype, PyTypeObject *type, const char *name)
-{
- PyDescrObject *descr;
-
- descr = (PyDescrObject *)PyType_GenericAlloc(descrtype, 0);
- if (descr != NULL) {
- Py_XINCREF(type);
- descr->d_type = type;
- descr->d_name = PyString_InternFromString(name);
- if (descr->d_name == NULL) {
- Py_DECREF(descr);
- descr = NULL;
- }
- }
- return descr;
-}
-
-PyObject *
-PyDescr_NewMethod(PyTypeObject *type, PyMethodDef *method)
-{
- PyMethodDescrObject *descr;
-
- descr = (PyMethodDescrObject *)descr_new(&PyMethodDescr_Type,
- type, method->ml_name);
- if (descr != NULL)
- descr->d_method = method;
- return (PyObject *)descr;
-}
-
-PyObject *
-PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
-{
- PyMethodDescrObject *descr;
-
- descr = (PyMethodDescrObject *)descr_new(&PyClassMethodDescr_Type,
- type, method->ml_name);
- if (descr != NULL)
- descr->d_method = method;
- return (PyObject *)descr;
-}
-
-PyObject *
-PyDescr_NewMember(PyTypeObject *type, PyMemberDef *member)
-{
- PyMemberDescrObject *descr;
-
- descr = (PyMemberDescrObject *)descr_new(&PyMemberDescr_Type,
- type, member->name);
- if (descr != NULL)
- descr->d_member = member;
- return (PyObject *)descr;
-}
-
-PyObject *
-PyDescr_NewGetSet(PyTypeObject *type, PyGetSetDef *getset)
-{
- PyGetSetDescrObject *descr;
-
- descr = (PyGetSetDescrObject *)descr_new(&PyGetSetDescr_Type,
- type, getset->name);
- if (descr != NULL)
- descr->d_getset = getset;
- return (PyObject *)descr;
-}
-
-PyObject *
-PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *base, void *wrapped)
-{
- PyWrapperDescrObject *descr;
-
- descr = (PyWrapperDescrObject *)descr_new(&PyWrapperDescr_Type,
- type, base->name);
- if (descr != NULL) {
- descr->d_base = base;
- descr->d_wrapped = wrapped;
- }
- return (PyObject *)descr;
-}
-
-
-/* --- Readonly proxy for dictionaries (actually any mapping) --- */
-
-/* This has no reason to be in this file except that adding new files is a
- bit of a pain */
-
-typedef struct {
- PyObject_HEAD
- PyObject *dict;
-} proxyobject;
-
-static Py_ssize_t
-proxy_len(proxyobject *pp)
-{
- return PyObject_Size(pp->dict);
-}
-
-static PyObject *
-proxy_getitem(proxyobject *pp, PyObject *key)
-{
- return PyObject_GetItem(pp->dict, key);
-}
-
-static PyMappingMethods proxy_as_mapping = {
- (lenfunc)proxy_len, /* mp_length */
- (binaryfunc)proxy_getitem, /* mp_subscript */
- 0, /* mp_ass_subscript */
-};
-
-static int
-proxy_contains(proxyobject *pp, PyObject *key)
-{
- return PyDict_Contains(pp->dict, key);
-}
-
-static PySequenceMethods proxy_as_sequence = {
- 0, /* sq_length */
- 0, /* sq_concat */
- 0, /* sq_repeat */
- 0, /* sq_item */
- 0, /* sq_slice */
- 0, /* sq_ass_item */
- 0, /* sq_ass_slice */
- (objobjproc)proxy_contains, /* sq_contains */
- 0, /* sq_inplace_concat */
- 0, /* sq_inplace_repeat */
-};
-
-static PyObject *
-proxy_has_key(proxyobject *pp, PyObject *key)
-{
- int res = PyDict_Contains(pp->dict, key);
- if (res < 0)
- return NULL;
- return PyBool_FromLong(res);
-}
-
-static PyObject *
-proxy_get(proxyobject *pp, PyObject *args)
-{
- PyObject *key, *def = Py_None;
-
- if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &def))
- return NULL;
- return PyObject_CallMethod(pp->dict, "get", "(OO)", key, def);
-}
-
-static PyObject *
-proxy_keys(proxyobject *pp)
-{
- return PyMapping_Keys(pp->dict);
-}
-
-static PyObject *
-proxy_values(proxyobject *pp)
-{
- return PyMapping_Values(pp->dict);
-}
-
-static PyObject *
-proxy_items(proxyobject *pp)
-{
- return PyMapping_Items(pp->dict);
-}
-
-static PyObject *
-proxy_iterkeys(proxyobject *pp)
-{
- return PyObject_CallMethod(pp->dict, "iterkeys", NULL);
-}
-
-static PyObject *
-proxy_itervalues(proxyobject *pp)
-{
- return PyObject_CallMethod(pp->dict, "itervalues", NULL);
-}
-
-static PyObject *
-proxy_iteritems(proxyobject *pp)
-{
- return PyObject_CallMethod(pp->dict, "iteritems", NULL);
-}
-static PyObject *
-proxy_copy(proxyobject *pp)
-{
- return PyObject_CallMethod(pp->dict, "copy", NULL);
-}
-
-static PyMethodDef proxy_methods[] = {
- {"has_key", (PyCFunction)proxy_has_key, METH_O,
- PyDoc_STR("D.has_key(k) -> True if D has a key k, else False")},
- {"get", (PyCFunction)proxy_get, METH_VARARGS,
- PyDoc_STR("D.get(k[,d]) -> D[k] if D.has_key(k), else d."
- " d defaults to None.")},
- {"keys", (PyCFunction)proxy_keys, METH_NOARGS,
- PyDoc_STR("D.keys() -> list of D's keys")},
- {"values", (PyCFunction)proxy_values, METH_NOARGS,
- PyDoc_STR("D.values() -> list of D's values")},
- {"items", (PyCFunction)proxy_items, METH_NOARGS,
- PyDoc_STR("D.items() -> list of D's (key, value) pairs, as 2-tuples")},
- {"iterkeys", (PyCFunction)proxy_iterkeys, METH_NOARGS,
- PyDoc_STR("D.iterkeys() -> an iterator over the keys of D")},
- {"itervalues",(PyCFunction)proxy_itervalues, METH_NOARGS,
- PyDoc_STR("D.itervalues() -> an iterator over the values of D")},
- {"iteritems", (PyCFunction)proxy_iteritems, METH_NOARGS,
- PyDoc_STR("D.iteritems() ->"
- " an iterator over the (key, value) items of D")},
- {"copy", (PyCFunction)proxy_copy, METH_NOARGS,
- PyDoc_STR("D.copy() -> a shallow copy of D")},
- {0}
-};
-
-static void
-proxy_dealloc(proxyobject *pp)
-{
- _PyObject_GC_UNTRACK(pp);
- Py_DECREF(pp->dict);
- PyObject_GC_Del(pp);
-}
-
-static PyObject *
-proxy_getiter(proxyobject *pp)
-{
- return PyObject_GetIter(pp->dict);
-}
-
-static PyObject *
-proxy_str(proxyobject *pp)
-{
- return PyObject_Str(pp->dict);
-}
-
-static int
-proxy_traverse(PyObject *self, visitproc visit, void *arg)
-{
- proxyobject *pp = (proxyobject *)self;
- Py_VISIT(pp->dict);
- return 0;
-}
-
-static int
-proxy_compare(proxyobject *v, PyObject *w)
-{
- return PyObject_Compare(v->dict, w);
-}
-
-static PyObject *
-proxy_richcompare(proxyobject *v, PyObject *w, int op)
-{
- return PyObject_RichCompare(v->dict, w, op);
-}
-
-static PyTypeObject proxytype = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "dictproxy", /* tp_name */
- sizeof(proxyobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)proxy_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)proxy_compare, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- &proxy_as_sequence, /* tp_as_sequence */
- &proxy_as_mapping, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)proxy_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- proxy_traverse, /* tp_traverse */
- 0, /* tp_clear */
- (richcmpfunc)proxy_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- (getiterfunc)proxy_getiter, /* tp_iter */
- 0, /* tp_iternext */
- proxy_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
-};
-
-PyObject *
-PyDictProxy_New(PyObject *dict)
-{
- proxyobject *pp;
-
- pp = PyObject_GC_New(proxyobject, &proxytype);
- if (pp != NULL) {
- Py_INCREF(dict);
- pp->dict = dict;
- _PyObject_GC_TRACK(pp);
- }
- return (PyObject *)pp;
-}
-
-
-/* --- Wrapper object for "slot" methods --- */
-
-/* This has no reason to be in this file except that adding new files is a
- bit of a pain */
-
-typedef struct {
- PyObject_HEAD
- PyWrapperDescrObject *descr;
- PyObject *self;
-} wrapperobject;
-
-static void
-wrapper_dealloc(wrapperobject *wp)
-{
- PyObject_GC_UnTrack(wp);
- Py_TRASHCAN_SAFE_BEGIN(wp)
- Py_XDECREF(wp->descr);
- Py_XDECREF(wp->self);
- PyObject_GC_Del(wp);
- Py_TRASHCAN_SAFE_END(wp)
-}
-
-static int
-wrapper_compare(wrapperobject *a, wrapperobject *b)
-{
- if (a->descr == b->descr)
- return PyObject_Compare(a->self, b->self);
- else
- return (a->descr < b->descr) ? -1 : 1;
-}
-
-static long
-wrapper_hash(wrapperobject *wp)
-{
- int x, y;
- x = _Py_HashPointer(wp->descr);
- if (x == -1)
- return -1;
- y = PyObject_Hash(wp->self);
- if (y == -1)
- return -1;
- x = x ^ y;
- if (x == -1)
- x = -2;
- return x;
-}
-
-static PyObject *
-wrapper_repr(wrapperobject *wp)
-{
- return PyString_FromFormat("<method-wrapper '%s' of %s object at %p>",
- wp->descr->d_base->name,
- wp->self->ob_type->tp_name,
- wp->self);
-}
-
-static PyMemberDef wrapper_members[] = {
- {"__self__", T_OBJECT, offsetof(wrapperobject, self), READONLY},
- {0}
-};
-
-static PyObject *
-wrapper_objclass(wrapperobject *wp)
-{
- PyObject *c = (PyObject *)wp->descr->d_type;
-
- Py_INCREF(c);
- return c;
-}
-
-static PyObject *
-wrapper_name(wrapperobject *wp)
-{
- char *s = wp->descr->d_base->name;
-
- return PyString_FromString(s);
-}
-
-static PyObject *
-wrapper_doc(wrapperobject *wp)
-{
- char *s = wp->descr->d_base->doc;
-
- if (s == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- else {
- return PyString_FromString(s);
- }
-}
-
-static PyGetSetDef wrapper_getsets[] = {
- {"__objclass__", (getter)wrapper_objclass},
- {"__name__", (getter)wrapper_name},
- {"__doc__", (getter)wrapper_doc},
- {0}
-};
-
-static PyObject *
-wrapper_call(wrapperobject *wp, PyObject *args, PyObject *kwds)
-{
- wrapperfunc wrapper = wp->descr->d_base->wrapper;
- PyObject *self = wp->self;
-
- if (wp->descr->d_base->flags & PyWrapperFlag_KEYWORDS) {
- wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
- return (*wk)(self, args, wp->descr->d_wrapped, kwds);
- }
-
- if (kwds != NULL && (!PyDict_Check(kwds) || PyDict_Size(kwds) != 0)) {
- PyErr_Format(PyExc_TypeError,
- "wrapper %s doesn't take keyword arguments",
- wp->descr->d_base->name);
- return NULL;
- }
- return (*wrapper)(self, args, wp->descr->d_wrapped);
-}
-
-static int
-wrapper_traverse(PyObject *self, visitproc visit, void *arg)
-{
- wrapperobject *wp = (wrapperobject *)self;
- Py_VISIT(wp->descr);
- Py_VISIT(wp->self);
- return 0;
-}
-
-static PyTypeObject wrappertype = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "method-wrapper", /* tp_name */
- sizeof(wrapperobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)wrapper_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)wrapper_compare, /* tp_compare */
- (reprfunc)wrapper_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)wrapper_hash, /* tp_hash */
- (ternaryfunc)wrapper_call, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- wrapper_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- wrapper_members, /* tp_members */
- wrapper_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
-};
-
-PyObject *
-PyWrapper_New(PyObject *d, PyObject *self)
-{
- wrapperobject *wp;
- PyWrapperDescrObject *descr;
-
- assert(PyObject_TypeCheck(d, &PyWrapperDescr_Type));
- descr = (PyWrapperDescrObject *)d;
- assert(PyObject_IsInstance(self, (PyObject *)(descr->d_type)));
-
- wp = PyObject_GC_New(wrapperobject, &wrappertype);
- if (wp != NULL) {
- Py_INCREF(descr);
- wp->descr = descr;
- Py_INCREF(self);
- wp->self = self;
- _PyObject_GC_TRACK(wp);
- }
- return (PyObject *)wp;
-}
-
-
-/* A built-in 'property' type */
-
-/*
- class property(object):
-
- def __init__(self, fget=None, fset=None, fdel=None, doc=None):
- if doc is None and fget is not None and hasattr(fget, "__doc__"):
- doc = fget.__doc__
- self.__get = fget
- self.__set = fset
- self.__del = fdel
- self.__doc__ = doc
-
- def __get__(self, inst, type=None):
- if inst is None:
- return self
- if self.__get is None:
- raise AttributeError, "unreadable attribute"
- return self.__get(inst)
-
- def __set__(self, inst, value):
- if self.__set is None:
- raise AttributeError, "can't set attribute"
- return self.__set(inst, value)
-
- def __delete__(self, inst):
- if self.__del is None:
- raise AttributeError, "can't delete attribute"
- return self.__del(inst)
-
-*/
-
-typedef struct {
- PyObject_HEAD
- PyObject *prop_get;
- PyObject *prop_set;
- PyObject *prop_del;
- PyObject *prop_doc;
-} propertyobject;
-
-static PyMemberDef property_members[] = {
- {"fget", T_OBJECT, offsetof(propertyobject, prop_get), READONLY},
- {"fset", T_OBJECT, offsetof(propertyobject, prop_set), READONLY},
- {"fdel", T_OBJECT, offsetof(propertyobject, prop_del), READONLY},
- {"__doc__", T_OBJECT, offsetof(propertyobject, prop_doc), READONLY},
- {0}
-};
-
-
-static void
-property_dealloc(PyObject *self)
-{
- propertyobject *gs = (propertyobject *)self;
-
- _PyObject_GC_UNTRACK(self);
- Py_XDECREF(gs->prop_get);
- Py_XDECREF(gs->prop_set);
- Py_XDECREF(gs->prop_del);
- Py_XDECREF(gs->prop_doc);
- self->ob_type->tp_free(self);
-}
-
-static PyObject *
-property_descr_get(PyObject *self, PyObject *obj, PyObject *type)
-{
- propertyobject *gs = (propertyobject *)self;
-
- if (obj == NULL || obj == Py_None) {
- Py_INCREF(self);
- return self;
- }
- if (gs->prop_get == NULL) {
- PyErr_SetString(PyExc_AttributeError, "unreadable attribute");
- return NULL;
- }
- return PyObject_CallFunction(gs->prop_get, "(O)", obj);
-}
-
-static int
-property_descr_set(PyObject *self, PyObject *obj, PyObject *value)
-{
- propertyobject *gs = (propertyobject *)self;
- PyObject *func, *res;
-
- if (value == NULL)
- func = gs->prop_del;
- else
- func = gs->prop_set;
- if (func == NULL) {
- PyErr_SetString(PyExc_AttributeError,
- value == NULL ?
- "can't delete attribute" :
- "can't set attribute");
- return -1;
- }
- if (value == NULL)
- res = PyObject_CallFunction(func, "(O)", obj);
- else
- res = PyObject_CallFunction(func, "(OO)", obj, value);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static int
-property_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- PyObject *get = NULL, *set = NULL, *del = NULL, *doc = NULL;
- static char *kwlist[] = {"fget", "fset", "fdel", "doc", 0};
- propertyobject *gs = (propertyobject *)self;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO:property",
- kwlist, &get, &set, &del, &doc))
- return -1;
-
- if (get == Py_None)
- get = NULL;
- if (set == Py_None)
- set = NULL;
- if (del == Py_None)
- del = NULL;
-
- Py_XINCREF(get);
- Py_XINCREF(set);
- Py_XINCREF(del);
- Py_XINCREF(doc);
-
- /* if no docstring given and the getter has one, use that one */
- if ((doc == NULL || doc == Py_None) && get != NULL) {
- PyObject *get_doc = PyObject_GetAttrString(get, "__doc__");
- if (get_doc != NULL) {
- Py_XDECREF(doc);
- doc = get_doc; /* get_doc already INCREF'd by GetAttr */
- } else {
- PyErr_Clear();
- }
- }
-
- gs->prop_get = get;
- gs->prop_set = set;
- gs->prop_del = del;
- gs->prop_doc = doc;
-
- return 0;
-}
-
-PyDoc_STRVAR(property_doc,
-"property(fget=None, fset=None, fdel=None, doc=None) -> property attribute\n"
-"\n"
-"fget is a function to be used for getting an attribute value, and likewise\n"
-"fset is a function for setting, and fdel a function for del'ing, an\n"
-"attribute. Typical use is to define a managed attribute x:\n"
-"class C(object):\n"
-" def getx(self): return self.__x\n"
-" def setx(self, value): self.__x = value\n"
-" def delx(self): del self.__x\n"
-" x = property(getx, setx, delx, \"I'm the 'x' property.\")");
-
-static int
-property_traverse(PyObject *self, visitproc visit, void *arg)
-{
- propertyobject *pp = (propertyobject *)self;
- Py_VISIT(pp->prop_get);
- Py_VISIT(pp->prop_set);
- Py_VISIT(pp->prop_del);
- Py_VISIT(pp->prop_doc);
- return 0;
-}
-
-PyTypeObject PyProperty_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "property", /* tp_name */
- sizeof(propertyobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- property_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- property_doc, /* tp_doc */
- property_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- property_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- property_descr_get, /* tp_descr_get */
- property_descr_set, /* tp_descr_set */
- 0, /* tp_dictoffset */
- property_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
diff --git a/sys/src/cmd/python/Objects/dictnotes.txt b/sys/src/cmd/python/Objects/dictnotes.txt
deleted file mode 100644
index b0e59a7f1..000000000
--- a/sys/src/cmd/python/Objects/dictnotes.txt
+++ /dev/null
@@ -1,250 +0,0 @@
-NOTES ON OPTIMIZING DICTIONARIES
-================================
-
-
-Principal Use Cases for Dictionaries
-------------------------------------
-
-Passing keyword arguments
- Typically, one read and one write for 1 to 3 elements.
- Occurs frequently in normal python code.
-
-Class method lookup
- Dictionaries vary in size with 8 to 16 elements being common.
- Usually written once with many lookups.
- When base classes are used, there are many failed lookups
- followed by a lookup in a base class.
-
-Instance attribute lookup and Global variables
- Dictionaries vary in size. 4 to 10 elements are common.
- Both reads and writes are common.
-
-Builtins
- Frequent reads. Almost never written.
- Size 126 interned strings (as of Py2.3b1).
- A few keys are accessed much more frequently than others.
-
-Uniquification
- Dictionaries of any size. Bulk of work is in creation.
- Repeated writes to a smaller set of keys.
- Single read of each key.
- Some use cases have two consecutive accesses to the same key.
-
- * Removing duplicates from a sequence.
- dict.fromkeys(seqn).keys()
-
- * Counting elements in a sequence.
- for e in seqn:
- d[e] = d.get(e,0) + 1
-
- * Accumulating references in a dictionary of lists:
-
- for pagenumber, page in enumerate(pages):
- for word in page:
- d.setdefault(word, []).append(pagenumber)
-
- Note, the second example is a use case characterized by a get and set
- to the same key. There are similar used cases with a __contains__
- followed by a get, set, or del to the same key. Part of the
- justification for d.setdefault is combining the two lookups into one.
-
-Membership Testing
- Dictionaries of any size. Created once and then rarely changes.
- Single write to each key.
- Many calls to __contains__() or has_key().
- Similar access patterns occur with replacement dictionaries
- such as with the % formatting operator.
-
-Dynamic Mappings
- Characterized by deletions interspersed with adds and replacements.
- Performance benefits greatly from the re-use of dummy entries.
-
-
-Data Layout (assuming a 32-bit box with 64 bytes per cache line)
-----------------------------------------------------------------
-
-Smalldicts (8 entries) are attached to the dictobject structure
-and the whole group nearly fills two consecutive cache lines.
-
-Larger dicts use the first half of the dictobject structure (one cache
-line) and a separate, continuous block of entries (at 12 bytes each
-for a total of 5.333 entries per cache line).
-
-
-Tunable Dictionary Parameters
------------------------------
-
-* PyDict_MINSIZE. Currently set to 8.
- Must be a power of two. New dicts have to zero-out every cell.
- Each additional 8 consumes 1.5 cache lines. Increasing improves
- the sparseness of small dictionaries but costs time to read in
- the additional cache lines if they are not already in cache.
- That case is common when keyword arguments are passed.
-
-* Maximum dictionary load in PyDict_SetItem. Currently set to 2/3.
- Increasing this ratio makes dictionaries more dense resulting
- in more collisions. Decreasing it improves sparseness at the
- expense of spreading entries over more cache lines and at the
- cost of total memory consumed.
-
- The load test occurs in highly time sensitive code. Efforts
- to make the test more complex (for example, varying the load
- for different sizes) have degraded performance.
-
-* Growth rate upon hitting maximum load. Currently set to *2.
- Raising this to *4 results in half the number of resizes,
- less effort to resize, better sparseness for some (but not
- all dict sizes), and potentially doubles memory consumption
- depending on the size of the dictionary. Setting to *4
- eliminates every other resize step.
-
-Tune-ups should be measured across a broad range of applications and
-use cases. A change to any parameter will help in some situations and
-hurt in others. The key is to find settings that help the most common
-cases and do the least damage to the less common cases. Results will
-vary dramatically depending on the exact number of keys, whether the
-keys are all strings, whether reads or writes dominate, the exact
-hash values of the keys (some sets of values have fewer collisions than
-others). Any one test or benchmark is likely to prove misleading.
-
-While making a dictionary more sparse reduces collisions, it impairs
-iteration and key listing. Those methods loop over every potential
-entry. Doubling the size of dictionary results in twice as many
-non-overlapping memory accesses for keys(), items(), values(),
-__iter__(), iterkeys(), iteritems(), itervalues(), and update().
-Also, every dictionary iterates at least twice, once for the memset()
-when it is created and once by dealloc().
-
-
-Results of Cache Locality Experiments
--------------------------------------
-
-When an entry is retrieved from memory, 4.333 adjacent entries are also
-retrieved into a cache line. Since accessing items in cache is *much*
-cheaper than a cache miss, an enticing idea is to probe the adjacent
-entries as a first step in collision resolution. Unfortunately, the
-introduction of any regularity into collision searches results in more
-collisions than the current random chaining approach.
-
-Exploiting cache locality at the expense of additional collisions fails
-to payoff when the entries are already loaded in cache (the expense
-is paid with no compensating benefit). This occurs in small dictionaries
-where the whole dictionary fits into a pair of cache lines. It also
-occurs frequently in large dictionaries which have a common access pattern
-where some keys are accessed much more frequently than others. The
-more popular entries *and* their collision chains tend to remain in cache.
-
-To exploit cache locality, change the collision resolution section
-in lookdict() and lookdict_string(). Set i^=1 at the top of the
-loop and move the i = (i << 2) + i + perturb + 1 to an unrolled
-version of the loop.
-
-This optimization strategy can be leveraged in several ways:
-
-* If the dictionary is kept sparse (through the tunable parameters),
-then the occurrence of additional collisions is lessened.
-
-* If lookdict() and lookdict_string() are specialized for small dicts
-and for largedicts, then the versions for large_dicts can be given
-an alternate search strategy without increasing collisions in small dicts
-which already have the maximum benefit of cache locality.
-
-* If the use case for a dictionary is known to have a random key
-access pattern (as opposed to a more common pattern with a Zipf's law
-distribution), then there will be more benefit for large dictionaries
-because any given key is no more likely than another to already be
-in cache.
-
-* In use cases with paired accesses to the same key, the second access
-is always in cache and gets no benefit from efforts to further improve
-cache locality.
-
-Optimizing the Search of Small Dictionaries
--------------------------------------------
-
-If lookdict() and lookdict_string() are specialized for smaller dictionaries,
-then a custom search approach can be implemented that exploits the small
-search space and cache locality.
-
-* The simplest example is a linear search of contiguous entries. This is
- simple to implement, guaranteed to terminate rapidly, never searches
- the same entry twice, and precludes the need to check for dummy entries.
-
-* A more advanced example is a self-organizing search so that the most
- frequently accessed entries get probed first. The organization
- adapts if the access pattern changes over time. Treaps are ideally
- suited for self-organization with the most common entries at the
- top of the heap and a rapid binary search pattern. Most probes and
- results are all located at the top of the tree allowing them all to
- be located in one or two cache lines.
-
-* Also, small dictionaries may be made more dense, perhaps filling all
- eight cells to take the maximum advantage of two cache lines.
-
-
-Strategy Pattern
-----------------
-
-Consider allowing the user to set the tunable parameters or to select a
-particular search method. Since some dictionary use cases have known
-sizes and access patterns, the user may be able to provide useful hints.
-
-1) For example, if membership testing or lookups dominate runtime and memory
- is not at a premium, the user may benefit from setting the maximum load
- ratio at 5% or 10% instead of the usual 66.7%. This will sharply
- curtail the number of collisions but will increase iteration time.
- The builtin namespace is a prime example of a dictionary that can
- benefit from being highly sparse.
-
-2) Dictionary creation time can be shortened in cases where the ultimate
- size of the dictionary is known in advance. The dictionary can be
- pre-sized so that no resize operations are required during creation.
- Not only does this save resizes, but the key insertion will go
- more quickly because the first half of the keys will be inserted into
- a more sparse environment than before. The preconditions for this
- strategy arise whenever a dictionary is created from a key or item
- sequence and the number of *unique* keys is known.
-
-3) If the key space is large and the access pattern is known to be random,
- then search strategies exploiting cache locality can be fruitful.
- The preconditions for this strategy arise in simulations and
- numerical analysis.
-
-4) If the keys are fixed and the access pattern strongly favors some of
- the keys, then the entries can be stored contiguously and accessed
- with a linear search or treap. This exploits knowledge of the data,
- cache locality, and a simplified search routine. It also eliminates
- the need to test for dummy entries on each probe. The preconditions
- for this strategy arise in symbol tables and in the builtin dictionary.
-
-
-Readonly Dictionaries
----------------------
-Some dictionary use cases pass through a build stage and then move to a
-more heavily exercised lookup stage with no further changes to the
-dictionary.
-
-An idea that emerged on python-dev is to be able to convert a dictionary
-to a read-only state. This can help prevent programming errors and also
-provide knowledge that can be exploited for lookup optimization.
-
-The dictionary can be immediately rebuilt (eliminating dummy entries),
-resized (to an appropriate level of sparseness), and the keys can be
-jostled (to minimize collisions). The lookdict() routine can then
-eliminate the test for dummy entries (saving about 1/4 of the time
-spent in the collision resolution loop).
-
-An additional possibility is to insert links into the empty spaces
-so that dictionary iteration can proceed in len(d) steps instead of
-(mp->mask + 1) steps. Alternatively, a separate tuple of keys can be
-kept just for iteration.
-
-
-Caching Lookups
----------------
-The idea is to exploit key access patterns by anticipating future lookups
-based on previous lookups.
-
-The simplest incarnation is to save the most recently accessed entry.
-This gives optimal performance for use cases where every get is followed
-by a set or del to the same key.
diff --git a/sys/src/cmd/python/Objects/dictobject.c b/sys/src/cmd/python/Objects/dictobject.c
deleted file mode 100644
index af0d6f37a..000000000
--- a/sys/src/cmd/python/Objects/dictobject.c
+++ /dev/null
@@ -1,2486 +0,0 @@
-
-/* Dictionary object implementation using a hash table */
-
-/* The distribution includes a separate file, Objects/dictnotes.txt,
- describing explorations into dictionary design and optimization.
- It covers typical dictionary use patterns, the parameters for
- tuning dictionaries, and several ideas for possible optimizations.
-*/
-
-#include "Python.h"
-
-typedef PyDictEntry dictentry;
-typedef PyDictObject dictobject;
-
-/* Set a key error with the specified argument, wrapping it in a
- * tuple automatically so that tuple keys are not unpacked as the
- * exception arguments. */
-static void
-set_key_error(PyObject *arg)
-{
- PyObject *tup;
- tup = PyTuple_Pack(1, arg);
- if (!tup)
- return; /* caller will expect error to be set anyway */
- PyErr_SetObject(PyExc_KeyError, tup);
- Py_DECREF(tup);
-}
-
-/* Define this out if you don't want conversion statistics on exit. */
-#undef SHOW_CONVERSION_COUNTS
-
-/* See large comment block below. This must be >= 1. */
-#define PERTURB_SHIFT 5
-
-/*
-Major subtleties ahead: Most hash schemes depend on having a "good" hash
-function, in the sense of simulating randomness. Python doesn't: its most
-important hash functions (for strings and ints) are very regular in common
-cases:
-
->>> map(hash, (0, 1, 2, 3))
-[0, 1, 2, 3]
->>> map(hash, ("namea", "nameb", "namec", "named"))
-[-1658398457, -1658398460, -1658398459, -1658398462]
->>>
-
-This isn't necessarily bad! To the contrary, in a table of size 2**i, taking
-the low-order i bits as the initial table index is extremely fast, and there
-are no collisions at all for dicts indexed by a contiguous range of ints.
-The same is approximately true when keys are "consecutive" strings. So this
-gives better-than-random behavior in common cases, and that's very desirable.
-
-OTOH, when collisions occur, the tendency to fill contiguous slices of the
-hash table makes a good collision resolution strategy crucial. Taking only
-the last i bits of the hash code is also vulnerable: for example, consider
-[i << 16 for i in range(20000)] as a set of keys. Since ints are their own
-hash codes, and this fits in a dict of size 2**15, the last 15 bits of every
-hash code are all 0: they *all* map to the same table index.
-
-But catering to unusual cases should not slow the usual ones, so we just take
-the last i bits anyway. It's up to collision resolution to do the rest. If
-we *usually* find the key we're looking for on the first try (and, it turns
-out, we usually do -- the table load factor is kept under 2/3, so the odds
-are solidly in our favor), then it makes best sense to keep the initial index
-computation dirt cheap.
-
-The first half of collision resolution is to visit table indices via this
-recurrence:
-
- j = ((5*j) + 1) mod 2**i
-
-For any initial j in range(2**i), repeating that 2**i times generates each
-int in range(2**i) exactly once (see any text on random-number generation for
-proof). By itself, this doesn't help much: like linear probing (setting
-j += 1, or j -= 1, on each loop trip), it scans the table entries in a fixed
-order. This would be bad, except that's not the only thing we do, and it's
-actually *good* in the common cases where hash keys are consecutive. In an
-example that's really too small to make this entirely clear, for a table of
-size 2**3 the order of indices is:
-
- 0 -> 1 -> 6 -> 7 -> 4 -> 5 -> 2 -> 3 -> 0 [and here it's repeating]
-
-If two things come in at index 5, the first place we look after is index 2,
-not 6, so if another comes in at index 6 the collision at 5 didn't hurt it.
-Linear probing is deadly in this case because there the fixed probe order
-is the *same* as the order consecutive keys are likely to arrive. But it's
-extremely unlikely hash codes will follow a 5*j+1 recurrence by accident,
-and certain that consecutive hash codes do not.
-
-The other half of the strategy is to get the other bits of the hash code
-into play. This is done by initializing a (unsigned) vrbl "perturb" to the
-full hash code, and changing the recurrence to:
-
- j = (5*j) + 1 + perturb;
- perturb >>= PERTURB_SHIFT;
- use j % 2**i as the next table index;
-
-Now the probe sequence depends (eventually) on every bit in the hash code,
-and the pseudo-scrambling property of recurring on 5*j+1 is more valuable,
-because it quickly magnifies small differences in the bits that didn't affect
-the initial index. Note that because perturb is unsigned, if the recurrence
-is executed often enough perturb eventually becomes and remains 0. At that
-point (very rarely reached) the recurrence is on (just) 5*j+1 again, and
-that's certain to find an empty slot eventually (since it generates every int
-in range(2**i), and we make sure there's always at least one empty slot).
-
-Selecting a good value for PERTURB_SHIFT is a balancing act. You want it
-small so that the high bits of the hash code continue to affect the probe
-sequence across iterations; but you want it large so that in really bad cases
-the high-order hash bits have an effect on early iterations. 5 was "the
-best" in minimizing total collisions across experiments Tim Peters ran (on
-both normal and pathological cases), but 4 and 6 weren't significantly worse.
-
-Historical: Reimer Behrends contributed the idea of using a polynomial-based
-approach, using repeated multiplication by x in GF(2**n) where an irreducible
-polynomial for each table size was chosen such that x was a primitive root.
-Christian Tismer later extended that to use division by x instead, as an
-efficient way to get the high bits of the hash code into play. This scheme
-also gave excellent collision statistics, but was more expensive: two
-if-tests were required inside the loop; computing "the next" index took about
-the same number of operations but without as much potential parallelism
-(e.g., computing 5*j can go on at the same time as computing 1+perturb in the
-above, and then shifting perturb can be done while the table index is being
-masked); and the dictobject struct required a member to hold the table's
-polynomial. In Tim's experiments the current scheme ran faster, produced
-equally good collision statistics, needed less code & used less memory.
-
-Theoretical Python 2.5 headache: hash codes are only C "long", but
-sizeof(Py_ssize_t) > sizeof(long) may be possible. In that case, and if a
-dict is genuinely huge, then only the slots directly reachable via indexing
-by a C long can be the first slot in a probe sequence. The probe sequence
-will still eventually reach every slot in the table, but the collision rate
-on initial probes may be much higher than this scheme was designed for.
-Getting a hash code as fat as Py_ssize_t is the only real cure. But in
-practice, this probably won't make a lick of difference for many years (at
-which point everyone will have terabytes of RAM on 64-bit boxes).
-*/
-
-/* Object used as dummy key to fill deleted entries */
-static PyObject *dummy = NULL; /* Initialized by first call to newdictobject() */
-
-#ifdef Py_REF_DEBUG
-PyObject *
-_PyDict_Dummy(void)
-{
- return dummy;
-}
-#endif
-
-/* forward declarations */
-static dictentry *
-lookdict_string(dictobject *mp, PyObject *key, long hash);
-
-#ifdef SHOW_CONVERSION_COUNTS
-static long created = 0L;
-static long converted = 0L;
-
-static void
-show_counts(void)
-{
- fprintf(stderr, "created %ld string dicts\n", created);
- fprintf(stderr, "converted %ld to normal dicts\n", converted);
- fprintf(stderr, "%.2f%% conversion rate\n", (100.0*converted)/created);
-}
-#endif
-
-/* Initialization macros.
- There are two ways to create a dict: PyDict_New() is the main C API
- function, and the tp_new slot maps to dict_new(). In the latter case we
- can save a little time over what PyDict_New does because it's guaranteed
- that the PyDictObject struct is already zeroed out.
- Everyone except dict_new() should use EMPTY_TO_MINSIZE (unless they have
- an excellent reason not to).
-*/
-
-#define INIT_NONZERO_DICT_SLOTS(mp) do { \
- (mp)->ma_table = (mp)->ma_smalltable; \
- (mp)->ma_mask = PyDict_MINSIZE - 1; \
- } while(0)
-
-#define EMPTY_TO_MINSIZE(mp) do { \
- memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \
- (mp)->ma_used = (mp)->ma_fill = 0; \
- INIT_NONZERO_DICT_SLOTS(mp); \
- } while(0)
-
-/* Dictionary reuse scheme to save calls to malloc, free, and memset */
-#define MAXFREEDICTS 80
-static PyDictObject *free_dicts[MAXFREEDICTS];
-static int num_free_dicts = 0;
-
-PyObject *
-PyDict_New(void)
-{
- register dictobject *mp;
- if (dummy == NULL) { /* Auto-initialize dummy */
- dummy = PyString_FromString("<dummy key>");
- if (dummy == NULL)
- return NULL;
-#ifdef SHOW_CONVERSION_COUNTS
- Py_AtExit(show_counts);
-#endif
- }
- if (num_free_dicts) {
- mp = free_dicts[--num_free_dicts];
- assert (mp != NULL);
- assert (mp->ob_type == &PyDict_Type);
- _Py_NewReference((PyObject *)mp);
- if (mp->ma_fill) {
- EMPTY_TO_MINSIZE(mp);
- }
- assert (mp->ma_used == 0);
- assert (mp->ma_table == mp->ma_smalltable);
- assert (mp->ma_mask == PyDict_MINSIZE - 1);
- } else {
- mp = PyObject_GC_New(dictobject, &PyDict_Type);
- if (mp == NULL)
- return NULL;
- EMPTY_TO_MINSIZE(mp);
- }
- mp->ma_lookup = lookdict_string;
-#ifdef SHOW_CONVERSION_COUNTS
- ++created;
-#endif
- _PyObject_GC_TRACK(mp);
- return (PyObject *)mp;
-}
-
-/*
-The basic lookup function used by all operations.
-This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
-Open addressing is preferred over chaining since the link overhead for
-chaining would be substantial (100% with typical malloc overhead).
-
-The initial probe index is computed as hash mod the table size. Subsequent
-probe indices are computed as explained earlier.
-
-All arithmetic on hash should ignore overflow.
-
-(The details in this version are due to Tim Peters, building on many past
-contributions by Reimer Behrends, Jyrki Alakuijala, Vladimir Marangozov and
-Christian Tismer).
-
-lookdict() is general-purpose, and may return NULL if (and only if) a
-comparison raises an exception (this was new in Python 2.5).
-lookdict_string() below is specialized to string keys, comparison of which can
-never raise an exception; that function can never return NULL. For both, when
-the key isn't found a dictentry* is returned for which the me_value field is
-NULL; this is the slot in the dict at which the key would have been found, and
-the caller can (if it wishes) add the <key, value> pair to the returned
-dictentry*.
-*/
-static dictentry *
-lookdict(dictobject *mp, PyObject *key, register long hash)
-{
- register size_t i;
- register size_t perturb;
- register dictentry *freeslot;
- register size_t mask = (size_t)mp->ma_mask;
- dictentry *ep0 = mp->ma_table;
- register dictentry *ep;
- register int cmp;
- PyObject *startkey;
-
- i = (size_t)hash & mask;
- ep = &ep0[i];
- if (ep->me_key == NULL || ep->me_key == key)
- return ep;
-
- if (ep->me_key == dummy)
- freeslot = ep;
- else {
- if (ep->me_hash == hash) {
- startkey = ep->me_key;
- cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
- if (cmp < 0)
- return NULL;
- if (ep0 == mp->ma_table && ep->me_key == startkey) {
- if (cmp > 0)
- return ep;
- }
- else {
- /* The compare did major nasty stuff to the
- * dict: start over.
- * XXX A clever adversary could prevent this
- * XXX from terminating.
- */
- return lookdict(mp, key, hash);
- }
- }
- freeslot = NULL;
- }
-
- /* In the loop, me_key == dummy is by far (factor of 100s) the
- least likely outcome, so test for that last. */
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- if (ep->me_key == NULL)
- return freeslot == NULL ? ep : freeslot;
- if (ep->me_key == key)
- return ep;
- if (ep->me_hash == hash && ep->me_key != dummy) {
- startkey = ep->me_key;
- cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
- if (cmp < 0)
- return NULL;
- if (ep0 == mp->ma_table && ep->me_key == startkey) {
- if (cmp > 0)
- return ep;
- }
- else {
- /* The compare did major nasty stuff to the
- * dict: start over.
- * XXX A clever adversary could prevent this
- * XXX from terminating.
- */
- return lookdict(mp, key, hash);
- }
- }
- else if (ep->me_key == dummy && freeslot == NULL)
- freeslot = ep;
- }
- assert(0); /* NOT REACHED */
- return 0;
-}
-
-/*
- * Hacked up version of lookdict which can assume keys are always strings;
- * this assumption allows testing for errors during PyObject_RichCompareBool()
- * to be dropped; string-string comparisons never raise exceptions. This also
- * means we don't need to go through PyObject_RichCompareBool(); we can always
- * use _PyString_Eq() directly.
- *
- * This is valuable because dicts with only string keys are very common.
- */
-static dictentry *
-lookdict_string(dictobject *mp, PyObject *key, register long hash)
-{
- register size_t i;
- register size_t perturb;
- register dictentry *freeslot;
- register size_t mask = (size_t)mp->ma_mask;
- dictentry *ep0 = mp->ma_table;
- register dictentry *ep;
-
- /* Make sure this function doesn't have to handle non-string keys,
- including subclasses of str; e.g., one reason to subclass
- strings is to override __eq__, and for speed we don't cater to
- that here. */
- if (!PyString_CheckExact(key)) {
-#ifdef SHOW_CONVERSION_COUNTS
- ++converted;
-#endif
- mp->ma_lookup = lookdict;
- return lookdict(mp, key, hash);
- }
- i = hash & mask;
- ep = &ep0[i];
- if (ep->me_key == NULL || ep->me_key == key)
- return ep;
- if (ep->me_key == dummy)
- freeslot = ep;
- else {
- if (ep->me_hash == hash && _PyString_Eq(ep->me_key, key))
- return ep;
- freeslot = NULL;
- }
-
- /* In the loop, me_key == dummy is by far (factor of 100s) the
- least likely outcome, so test for that last. */
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- if (ep->me_key == NULL)
- return freeslot == NULL ? ep : freeslot;
- if (ep->me_key == key
- || (ep->me_hash == hash
- && ep->me_key != dummy
- && _PyString_Eq(ep->me_key, key)))
- return ep;
- if (ep->me_key == dummy && freeslot == NULL)
- freeslot = ep;
- }
- assert(0); /* NOT REACHED */
- return 0;
-}
-
-/*
-Internal routine to insert a new item into the table.
-Used both by the internal resize routine and by the public insert routine.
-Eats a reference to key and one to value.
-Returns -1 if an error occurred, or 0 on success.
-*/
-static int
-insertdict(register dictobject *mp, PyObject *key, long hash, PyObject *value)
-{
- PyObject *old_value;
- register dictentry *ep;
- typedef PyDictEntry *(*lookupfunc)(PyDictObject *, PyObject *, long);
-
- assert(mp->ma_lookup != NULL);
- ep = mp->ma_lookup(mp, key, hash);
- if (ep == NULL) {
- Py_DECREF(key);
- Py_DECREF(value);
- return -1;
- }
- if (ep->me_value != NULL) {
- old_value = ep->me_value;
- ep->me_value = value;
- Py_DECREF(old_value); /* which **CAN** re-enter */
- Py_DECREF(key);
- }
- else {
- if (ep->me_key == NULL)
- mp->ma_fill++;
- else {
- assert(ep->me_key == dummy);
- Py_DECREF(dummy);
- }
- ep->me_key = key;
- ep->me_hash = (Py_ssize_t)hash;
- ep->me_value = value;
- mp->ma_used++;
- }
- return 0;
-}
-
-/*
-Internal routine used by dictresize() to insert an item which is
-known to be absent from the dict. This routine also assumes that
-the dict contains no deleted entries. Besides the performance benefit,
-using insertdict() in dictresize() is dangerous (SF bug #1456209).
-Note that no refcounts are changed by this routine; if needed, the caller
-is responsible for incref'ing `key` and `value`.
-*/
-static void
-insertdict_clean(register dictobject *mp, PyObject *key, long hash,
- PyObject *value)
-{
- register size_t i;
- register size_t perturb;
- register size_t mask = (size_t)mp->ma_mask;
- dictentry *ep0 = mp->ma_table;
- register dictentry *ep;
-
- i = hash & mask;
- ep = &ep0[i];
- for (perturb = hash; ep->me_key != NULL; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- ep = &ep0[i & mask];
- }
- assert(ep->me_value == NULL);
- mp->ma_fill++;
- ep->me_key = key;
- ep->me_hash = (Py_ssize_t)hash;
- ep->me_value = value;
- mp->ma_used++;
-}
-
-/*
-Restructure the table by allocating a new table and reinserting all
-items again. When entries have been deleted, the new table may
-actually be smaller than the old one.
-*/
-static int
-dictresize(dictobject *mp, Py_ssize_t minused)
-{
- Py_ssize_t newsize;
- dictentry *oldtable, *newtable, *ep;
- Py_ssize_t i;
- int is_oldtable_malloced;
- dictentry small_copy[PyDict_MINSIZE];
-
- assert(minused >= 0);
-
- /* Find the smallest table size > minused. */
- for (newsize = PyDict_MINSIZE;
- newsize <= minused && newsize > 0;
- newsize <<= 1)
- ;
- if (newsize <= 0) {
- PyErr_NoMemory();
- return -1;
- }
-
- /* Get space for a new table. */
- oldtable = mp->ma_table;
- assert(oldtable != NULL);
- is_oldtable_malloced = oldtable != mp->ma_smalltable;
-
- if (newsize == PyDict_MINSIZE) {
- /* A large table is shrinking, or we can't get any smaller. */
- newtable = mp->ma_smalltable;
- if (newtable == oldtable) {
- if (mp->ma_fill == mp->ma_used) {
- /* No dummies, so no point doing anything. */
- return 0;
- }
- /* We're not going to resize it, but rebuild the
- table anyway to purge old dummy entries.
- Subtle: This is *necessary* if fill==size,
- as lookdict needs at least one virgin slot to
- terminate failing searches. If fill < size, it's
- merely desirable, as dummies slow searches. */
- assert(mp->ma_fill > mp->ma_used);
- memcpy(small_copy, oldtable, sizeof(small_copy));
- oldtable = small_copy;
- }
- }
- else {
- newtable = PyMem_NEW(dictentry, newsize);
- if (newtable == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- }
-
- /* Make the dict empty, using the new table. */
- assert(newtable != oldtable);
- mp->ma_table = newtable;
- mp->ma_mask = newsize - 1;
- memset(newtable, 0, sizeof(dictentry) * newsize);
- mp->ma_used = 0;
- i = mp->ma_fill;
- mp->ma_fill = 0;
-
- /* Copy the data over; this is refcount-neutral for active entries;
- dummy entries aren't copied over, of course */
- for (ep = oldtable; i > 0; ep++) {
- if (ep->me_value != NULL) { /* active entry */
- --i;
- insertdict_clean(mp, ep->me_key, (long)ep->me_hash,
- ep->me_value);
- }
- else if (ep->me_key != NULL) { /* dummy entry */
- --i;
- assert(ep->me_key == dummy);
- Py_DECREF(ep->me_key);
- }
- /* else key == value == NULL: nothing to do */
- }
-
- if (is_oldtable_malloced)
- PyMem_DEL(oldtable);
- return 0;
-}
-
-/* Note that, for historical reasons, PyDict_GetItem() suppresses all errors
- * that may occur (originally dicts supported only string keys, and exceptions
- * weren't possible). So, while the original intent was that a NULL return
- * meant the key wasn't present, in reality it can mean that, or that an error
- * (suppressed) occurred while computing the key's hash, or that some error
- * (suppressed) occurred when comparing keys in the dict's internal probe
- * sequence. A nasty example of the latter is when a Python-coded comparison
- * function hits a stack-depth error, which can cause this to return NULL
- * even if the key is present.
- */
-PyObject *
-PyDict_GetItem(PyObject *op, PyObject *key)
-{
- long hash;
- dictobject *mp = (dictobject *)op;
- dictentry *ep;
- PyThreadState *tstate;
- if (!PyDict_Check(op))
- return NULL;
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1)
- {
- hash = PyObject_Hash(key);
- if (hash == -1) {
- PyErr_Clear();
- return NULL;
- }
- }
-
- /* We can arrive here with a NULL tstate during initialization:
- try running "python -Wi" for an example related to string
- interning. Let's just hope that no exception occurs then... */
- tstate = _PyThreadState_Current;
- if (tstate != NULL && tstate->curexc_type != NULL) {
- /* preserve the existing exception */
- PyObject *err_type, *err_value, *err_tb;
- PyErr_Fetch(&err_type, &err_value, &err_tb);
- ep = (mp->ma_lookup)(mp, key, hash);
- /* ignore errors */
- PyErr_Restore(err_type, err_value, err_tb);
- if (ep == NULL)
- return NULL;
- }
- else {
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep == NULL) {
- PyErr_Clear();
- return NULL;
- }
- }
- return ep->me_value;
-}
-
-/* CAUTION: PyDict_SetItem() must guarantee that it won't resize the
- * dictionary if it's merely replacing the value for an existing key.
- * This means that it's safe to loop over a dictionary with PyDict_Next()
- * and occasionally replace a value -- but you can't insert new keys or
- * remove them.
- */
-int
-PyDict_SetItem(register PyObject *op, PyObject *key, PyObject *value)
-{
- register dictobject *mp;
- register long hash;
- register Py_ssize_t n_used;
-
- if (!PyDict_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- assert(key);
- assert(value);
- mp = (dictobject *)op;
- if (PyString_CheckExact(key)) {
- hash = ((PyStringObject *)key)->ob_shash;
- if (hash == -1)
- hash = PyObject_Hash(key);
- }
- else {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return -1;
- }
- assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */
- n_used = mp->ma_used;
- Py_INCREF(value);
- Py_INCREF(key);
- if (insertdict(mp, key, hash, value) != 0)
- return -1;
- /* If we added a key, we can safely resize. Otherwise just return!
- * If fill >= 2/3 size, adjust size. Normally, this doubles or
- * quaduples the size, but it's also possible for the dict to shrink
- * (if ma_fill is much larger than ma_used, meaning a lot of dict
- * keys have been * deleted).
- *
- * Quadrupling the size improves average dictionary sparseness
- * (reducing collisions) at the cost of some memory and iteration
- * speed (which loops over every possible entry). It also halves
- * the number of expensive resize operations in a growing dictionary.
- *
- * Very large dictionaries (over 50K items) use doubling instead.
- * This may help applications with severe memory constraints.
- */
- if (!(mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2))
- return 0;
- return dictresize(mp, (mp->ma_used > 50000 ? 2 : 4) * mp->ma_used);
-}
-
-int
-PyDict_DelItem(PyObject *op, PyObject *key)
-{
- register dictobject *mp;
- register long hash;
- register dictentry *ep;
- PyObject *old_value, *old_key;
-
- if (!PyDict_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- assert(key);
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return -1;
- }
- mp = (dictobject *)op;
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep == NULL)
- return -1;
- if (ep->me_value == NULL) {
- set_key_error(key);
- return -1;
- }
- old_key = ep->me_key;
- Py_INCREF(dummy);
- ep->me_key = dummy;
- old_value = ep->me_value;
- ep->me_value = NULL;
- mp->ma_used--;
- Py_DECREF(old_value);
- Py_DECREF(old_key);
- return 0;
-}
-
-void
-PyDict_Clear(PyObject *op)
-{
- dictobject *mp;
- dictentry *ep, *table;
- int table_is_malloced;
- Py_ssize_t fill;
- dictentry small_copy[PyDict_MINSIZE];
-#ifdef Py_DEBUG
- Py_ssize_t i, n;
-#endif
-
- if (!PyDict_Check(op))
- return;
- mp = (dictobject *)op;
-#ifdef Py_DEBUG
- n = mp->ma_mask + 1;
- i = 0;
-#endif
-
- table = mp->ma_table;
- assert(table != NULL);
- table_is_malloced = table != mp->ma_smalltable;
-
- /* This is delicate. During the process of clearing the dict,
- * decrefs can cause the dict to mutate. To avoid fatal confusion
- * (voice of experience), we have to make the dict empty before
- * clearing the slots, and never refer to anything via mp->xxx while
- * clearing.
- */
- fill = mp->ma_fill;
- if (table_is_malloced)
- EMPTY_TO_MINSIZE(mp);
-
- else if (fill > 0) {
- /* It's a small table with something that needs to be cleared.
- * Afraid the only safe way is to copy the dict entries into
- * another small table first.
- */
- memcpy(small_copy, table, sizeof(small_copy));
- table = small_copy;
- EMPTY_TO_MINSIZE(mp);
- }
- /* else it's a small table that's already empty */
-
- /* Now we can finally clear things. If C had refcounts, we could
- * assert that the refcount on table is 1 now, i.e. that this function
- * has unique access to it, so decref side-effects can't alter it.
- */
- for (ep = table; fill > 0; ++ep) {
-#ifdef Py_DEBUG
- assert(i < n);
- ++i;
-#endif
- if (ep->me_key) {
- --fill;
- Py_DECREF(ep->me_key);
- Py_XDECREF(ep->me_value);
- }
-#ifdef Py_DEBUG
- else
- assert(ep->me_value == NULL);
-#endif
- }
-
- if (table_is_malloced)
- PyMem_DEL(table);
-}
-
-/*
- * Iterate over a dict. Use like so:
- *
- * Py_ssize_t i;
- * PyObject *key, *value;
- * i = 0; # important! i should not otherwise be changed by you
- * while (PyDict_Next(yourdict, &i, &key, &value)) {
- * Refer to borrowed references in key and value.
- * }
- *
- * CAUTION: In general, it isn't safe to use PyDict_Next in a loop that
- * mutates the dict. One exception: it is safe if the loop merely changes
- * the values associated with the keys (but doesn't insert new keys or
- * delete keys), via PyDict_SetItem().
- */
-int
-PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
-{
- register Py_ssize_t i;
- register Py_ssize_t mask;
- register dictentry *ep;
-
- if (!PyDict_Check(op))
- return 0;
- i = *ppos;
- if (i < 0)
- return 0;
- ep = ((dictobject *)op)->ma_table;
- mask = ((dictobject *)op)->ma_mask;
- while (i <= mask && ep[i].me_value == NULL)
- i++;
- *ppos = i+1;
- if (i > mask)
- return 0;
- if (pkey)
- *pkey = ep[i].me_key;
- if (pvalue)
- *pvalue = ep[i].me_value;
- return 1;
-}
-
-/* Internal version of PyDict_Next that returns a hash value in addition to the key and value.*/
-int
-_PyDict_Next(PyObject *op, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue, long *phash)
-{
- register Py_ssize_t i;
- register Py_ssize_t mask;
- register dictentry *ep;
-
- if (!PyDict_Check(op))
- return 0;
- i = *ppos;
- if (i < 0)
- return 0;
- ep = ((dictobject *)op)->ma_table;
- mask = ((dictobject *)op)->ma_mask;
- while (i <= mask && ep[i].me_value == NULL)
- i++;
- *ppos = i+1;
- if (i > mask)
- return 0;
- *phash = (long)(ep[i].me_hash);
- if (pkey)
- *pkey = ep[i].me_key;
- if (pvalue)
- *pvalue = ep[i].me_value;
- return 1;
-}
-
-/* Methods */
-
-static void
-dict_dealloc(register dictobject *mp)
-{
- register dictentry *ep;
- Py_ssize_t fill = mp->ma_fill;
- PyObject_GC_UnTrack(mp);
- Py_TRASHCAN_SAFE_BEGIN(mp)
- for (ep = mp->ma_table; fill > 0; ep++) {
- if (ep->me_key) {
- --fill;
- Py_DECREF(ep->me_key);
- Py_XDECREF(ep->me_value);
- }
- }
- if (mp->ma_table != mp->ma_smalltable)
- PyMem_DEL(mp->ma_table);
- if (num_free_dicts < MAXFREEDICTS && mp->ob_type == &PyDict_Type)
- free_dicts[num_free_dicts++] = mp;
- else
- mp->ob_type->tp_free((PyObject *)mp);
- Py_TRASHCAN_SAFE_END(mp)
-}
-
-static int
-dict_print(register dictobject *mp, register FILE *fp, register int flags)
-{
- register Py_ssize_t i;
- register Py_ssize_t any;
- int status;
-
- status = Py_ReprEnter((PyObject*)mp);
- if (status != 0) {
- if (status < 0)
- return status;
- fprintf(fp, "{...}");
- return 0;
- }
-
- fprintf(fp, "{");
- any = 0;
- for (i = 0; i <= mp->ma_mask; i++) {
- dictentry *ep = mp->ma_table + i;
- PyObject *pvalue = ep->me_value;
- if (pvalue != NULL) {
- /* Prevent PyObject_Repr from deleting value during
- key format */
- Py_INCREF(pvalue);
- if (any++ > 0)
- fprintf(fp, ", ");
- if (PyObject_Print((PyObject *)ep->me_key, fp, 0)!=0) {
- Py_DECREF(pvalue);
- Py_ReprLeave((PyObject*)mp);
- return -1;
- }
- fprintf(fp, ": ");
- if (PyObject_Print(pvalue, fp, 0) != 0) {
- Py_DECREF(pvalue);
- Py_ReprLeave((PyObject*)mp);
- return -1;
- }
- Py_DECREF(pvalue);
- }
- }
- fprintf(fp, "}");
- Py_ReprLeave((PyObject*)mp);
- return 0;
-}
-
-static PyObject *
-dict_repr(dictobject *mp)
-{
- Py_ssize_t i;
- PyObject *s, *temp, *colon = NULL;
- PyObject *pieces = NULL, *result = NULL;
- PyObject *key, *value;
-
- i = Py_ReprEnter((PyObject *)mp);
- if (i != 0) {
- return i > 0 ? PyString_FromString("{...}") : NULL;
- }
-
- if (mp->ma_used == 0) {
- result = PyString_FromString("{}");
- goto Done;
- }
-
- pieces = PyList_New(0);
- if (pieces == NULL)
- goto Done;
-
- colon = PyString_FromString(": ");
- if (colon == NULL)
- goto Done;
-
- /* Do repr() on each key+value pair, and insert ": " between them.
- Note that repr may mutate the dict. */
- i = 0;
- while (PyDict_Next((PyObject *)mp, &i, &key, &value)) {
- int status;
- /* Prevent repr from deleting value during key format. */
- Py_INCREF(value);
- s = PyObject_Repr(key);
- PyString_Concat(&s, colon);
- PyString_ConcatAndDel(&s, PyObject_Repr(value));
- Py_DECREF(value);
- if (s == NULL)
- goto Done;
- status = PyList_Append(pieces, s);
- Py_DECREF(s); /* append created a new ref */
- if (status < 0)
- goto Done;
- }
-
- /* Add "{}" decorations to the first and last items. */
- assert(PyList_GET_SIZE(pieces) > 0);
- s = PyString_FromString("{");
- if (s == NULL)
- goto Done;
- temp = PyList_GET_ITEM(pieces, 0);
- PyString_ConcatAndDel(&s, temp);
- PyList_SET_ITEM(pieces, 0, s);
- if (s == NULL)
- goto Done;
-
- s = PyString_FromString("}");
- if (s == NULL)
- goto Done;
- temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
- PyString_ConcatAndDel(&temp, s);
- PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
- if (temp == NULL)
- goto Done;
-
- /* Paste them all together with ", " between. */
- s = PyString_FromString(", ");
- if (s == NULL)
- goto Done;
- result = _PyString_Join(s, pieces);
- Py_DECREF(s);
-
-Done:
- Py_XDECREF(pieces);
- Py_XDECREF(colon);
- Py_ReprLeave((PyObject *)mp);
- return result;
-}
-
-static Py_ssize_t
-dict_length(dictobject *mp)
-{
- return mp->ma_used;
-}
-
-static PyObject *
-dict_subscript(dictobject *mp, register PyObject *key)
-{
- PyObject *v;
- long hash;
- dictentry *ep;
- assert(mp->ma_table != NULL);
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return NULL;
- }
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep == NULL)
- return NULL;
- v = ep->me_value;
- if (v == NULL) {
- if (!PyDict_CheckExact(mp)) {
- /* Look up __missing__ method if we're a subclass. */
- PyObject *missing;
- static PyObject *missing_str = NULL;
- if (missing_str == NULL)
- missing_str =
- PyString_InternFromString("__missing__");
- missing = _PyType_Lookup(mp->ob_type, missing_str);
- if (missing != NULL)
- return PyObject_CallFunctionObjArgs(missing,
- (PyObject *)mp, key, NULL);
- }
- set_key_error(key);
- return NULL;
- }
- else
- Py_INCREF(v);
- return v;
-}
-
-static int
-dict_ass_sub(dictobject *mp, PyObject *v, PyObject *w)
-{
- if (w == NULL)
- return PyDict_DelItem((PyObject *)mp, v);
- else
- return PyDict_SetItem((PyObject *)mp, v, w);
-}
-
-static PyMappingMethods dict_as_mapping = {
- (lenfunc)dict_length, /*mp_length*/
- (binaryfunc)dict_subscript, /*mp_subscript*/
- (objobjargproc)dict_ass_sub, /*mp_ass_subscript*/
-};
-
-static PyObject *
-dict_keys(register dictobject *mp)
-{
- register PyObject *v;
- register Py_ssize_t i, j;
- dictentry *ep;
- Py_ssize_t mask, n;
-
- again:
- n = mp->ma_used;
- v = PyList_New(n);
- if (v == NULL)
- return NULL;
- if (n != mp->ma_used) {
- /* Durnit. The allocations caused the dict to resize.
- * Just start over, this shouldn't normally happen.
- */
- Py_DECREF(v);
- goto again;
- }
- ep = mp->ma_table;
- mask = mp->ma_mask;
- for (i = 0, j = 0; i <= mask; i++) {
- if (ep[i].me_value != NULL) {
- PyObject *key = ep[i].me_key;
- Py_INCREF(key);
- PyList_SET_ITEM(v, j, key);
- j++;
- }
- }
- assert(j == n);
- return v;
-}
-
-static PyObject *
-dict_values(register dictobject *mp)
-{
- register PyObject *v;
- register Py_ssize_t i, j;
- dictentry *ep;
- Py_ssize_t mask, n;
-
- again:
- n = mp->ma_used;
- v = PyList_New(n);
- if (v == NULL)
- return NULL;
- if (n != mp->ma_used) {
- /* Durnit. The allocations caused the dict to resize.
- * Just start over, this shouldn't normally happen.
- */
- Py_DECREF(v);
- goto again;
- }
- ep = mp->ma_table;
- mask = mp->ma_mask;
- for (i = 0, j = 0; i <= mask; i++) {
- if (ep[i].me_value != NULL) {
- PyObject *value = ep[i].me_value;
- Py_INCREF(value);
- PyList_SET_ITEM(v, j, value);
- j++;
- }
- }
- assert(j == n);
- return v;
-}
-
-static PyObject *
-dict_items(register dictobject *mp)
-{
- register PyObject *v;
- register Py_ssize_t i, j, n;
- Py_ssize_t mask;
- PyObject *item, *key, *value;
- dictentry *ep;
-
- /* Preallocate the list of tuples, to avoid allocations during
- * the loop over the items, which could trigger GC, which
- * could resize the dict. :-(
- */
- again:
- n = mp->ma_used;
- v = PyList_New(n);
- if (v == NULL)
- return NULL;
- for (i = 0; i < n; i++) {
- item = PyTuple_New(2);
- if (item == NULL) {
- Py_DECREF(v);
- return NULL;
- }
- PyList_SET_ITEM(v, i, item);
- }
- if (n != mp->ma_used) {
- /* Durnit. The allocations caused the dict to resize.
- * Just start over, this shouldn't normally happen.
- */
- Py_DECREF(v);
- goto again;
- }
- /* Nothing we do below makes any function calls. */
- ep = mp->ma_table;
- mask = mp->ma_mask;
- for (i = 0, j = 0; i <= mask; i++) {
- if ((value=ep[i].me_value) != NULL) {
- key = ep[i].me_key;
- item = PyList_GET_ITEM(v, j);
- Py_INCREF(key);
- PyTuple_SET_ITEM(item, 0, key);
- Py_INCREF(value);
- PyTuple_SET_ITEM(item, 1, value);
- j++;
- }
- }
- assert(j == n);
- return v;
-}
-
-static PyObject *
-dict_fromkeys(PyObject *cls, PyObject *args)
-{
- PyObject *seq;
- PyObject *value = Py_None;
- PyObject *it; /* iter(seq) */
- PyObject *key;
- PyObject *d;
- int status;
-
- if (!PyArg_UnpackTuple(args, "fromkeys", 1, 2, &seq, &value))
- return NULL;
-
- d = PyObject_CallObject(cls, NULL);
- if (d == NULL)
- return NULL;
-
- if (PyDict_CheckExact(d) && PyAnySet_CheckExact(seq)) {
- dictobject *mp = (dictobject *)d;
- Py_ssize_t pos = 0;
- PyObject *key;
- long hash;
-
- if (dictresize(mp, PySet_GET_SIZE(seq)))
- return NULL;
-
- while (_PySet_NextEntry(seq, &pos, &key, &hash)) {
- Py_INCREF(key);
- Py_INCREF(value);
- if (insertdict(mp, key, hash, value))
- return NULL;
- }
- return d;
- }
-
- it = PyObject_GetIter(seq);
- if (it == NULL){
- Py_DECREF(d);
- return NULL;
- }
-
- for (;;) {
- key = PyIter_Next(it);
- if (key == NULL) {
- if (PyErr_Occurred())
- goto Fail;
- break;
- }
- status = PyObject_SetItem(d, key, value);
- Py_DECREF(key);
- if (status < 0)
- goto Fail;
- }
-
- Py_DECREF(it);
- return d;
-
-Fail:
- Py_DECREF(it);
- Py_DECREF(d);
- return NULL;
-}
-
-static int
-dict_update_common(PyObject *self, PyObject *args, PyObject *kwds, char *methname)
-{
- PyObject *arg = NULL;
- int result = 0;
-
- if (!PyArg_UnpackTuple(args, methname, 0, 1, &arg))
- result = -1;
-
- else if (arg != NULL) {
- if (PyObject_HasAttrString(arg, "keys"))
- result = PyDict_Merge(self, arg, 1);
- else
- result = PyDict_MergeFromSeq2(self, arg, 1);
- }
- if (result == 0 && kwds != NULL)
- result = PyDict_Merge(self, kwds, 1);
- return result;
-}
-
-static PyObject *
-dict_update(PyObject *self, PyObject *args, PyObject *kwds)
-{
- if (dict_update_common(self, args, kwds, "update") != -1)
- Py_RETURN_NONE;
- return NULL;
-}
-
-/* Update unconditionally replaces existing items.
- Merge has a 3rd argument 'override'; if set, it acts like Update,
- otherwise it leaves existing items unchanged.
-
- PyDict_{Update,Merge} update/merge from a mapping object.
-
- PyDict_MergeFromSeq2 updates/merges from any iterable object
- producing iterable objects of length 2.
-*/
-
-int
-PyDict_MergeFromSeq2(PyObject *d, PyObject *seq2, int override)
-{
- PyObject *it; /* iter(seq2) */
- Py_ssize_t i; /* index into seq2 of current element */
- PyObject *item; /* seq2[i] */
- PyObject *fast; /* item as a 2-tuple or 2-list */
-
- assert(d != NULL);
- assert(PyDict_Check(d));
- assert(seq2 != NULL);
-
- it = PyObject_GetIter(seq2);
- if (it == NULL)
- return -1;
-
- for (i = 0; ; ++i) {
- PyObject *key, *value;
- Py_ssize_t n;
-
- fast = NULL;
- item = PyIter_Next(it);
- if (item == NULL) {
- if (PyErr_Occurred())
- goto Fail;
- break;
- }
-
- /* Convert item to sequence, and verify length 2. */
- fast = PySequence_Fast(item, "");
- if (fast == NULL) {
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError,
- "cannot convert dictionary update "
- "sequence element #%zd to a sequence",
- i);
- goto Fail;
- }
- n = PySequence_Fast_GET_SIZE(fast);
- if (n != 2) {
- PyErr_Format(PyExc_ValueError,
- "dictionary update sequence element #%zd "
- "has length %zd; 2 is required",
- i, n);
- goto Fail;
- }
-
- /* Update/merge with this (key, value) pair. */
- key = PySequence_Fast_GET_ITEM(fast, 0);
- value = PySequence_Fast_GET_ITEM(fast, 1);
- if (override || PyDict_GetItem(d, key) == NULL) {
- int status = PyDict_SetItem(d, key, value);
- if (status < 0)
- goto Fail;
- }
- Py_DECREF(fast);
- Py_DECREF(item);
- }
-
- i = 0;
- goto Return;
-Fail:
- Py_XDECREF(item);
- Py_XDECREF(fast);
- i = -1;
-Return:
- Py_DECREF(it);
- return Py_SAFE_DOWNCAST(i, Py_ssize_t, int);
-}
-
-int
-PyDict_Update(PyObject *a, PyObject *b)
-{
- return PyDict_Merge(a, b, 1);
-}
-
-int
-PyDict_Merge(PyObject *a, PyObject *b, int override)
-{
- register PyDictObject *mp, *other;
- register Py_ssize_t i;
- dictentry *entry;
-
- /* We accept for the argument either a concrete dictionary object,
- * or an abstract "mapping" object. For the former, we can do
- * things quite efficiently. For the latter, we only require that
- * PyMapping_Keys() and PyObject_GetItem() be supported.
- */
- if (a == NULL || !PyDict_Check(a) || b == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
- mp = (dictobject*)a;
- if (PyDict_Check(b)) {
- other = (dictobject*)b;
- if (other == mp || other->ma_used == 0)
- /* a.update(a) or a.update({}); nothing to do */
- return 0;
- if (mp->ma_used == 0)
- /* Since the target dict is empty, PyDict_GetItem()
- * always returns NULL. Setting override to 1
- * skips the unnecessary test.
- */
- override = 1;
- /* Do one big resize at the start, rather than
- * incrementally resizing as we insert new items. Expect
- * that there will be no (or few) overlapping keys.
- */
- if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) {
- if (dictresize(mp, (mp->ma_used + other->ma_used)*2) != 0)
- return -1;
- }
- for (i = 0; i <= other->ma_mask; i++) {
- entry = &other->ma_table[i];
- if (entry->me_value != NULL &&
- (override ||
- PyDict_GetItem(a, entry->me_key) == NULL)) {
- Py_INCREF(entry->me_key);
- Py_INCREF(entry->me_value);
- if (insertdict(mp, entry->me_key,
- (long)entry->me_hash,
- entry->me_value) != 0)
- return -1;
- }
- }
- }
- else {
- /* Do it the generic, slower way */
- PyObject *keys = PyMapping_Keys(b);
- PyObject *iter;
- PyObject *key, *value;
- int status;
-
- if (keys == NULL)
- /* Docstring says this is equivalent to E.keys() so
- * if E doesn't have a .keys() method we want
- * AttributeError to percolate up. Might as well
- * do the same for any other error.
- */
- return -1;
-
- iter = PyObject_GetIter(keys);
- Py_DECREF(keys);
- if (iter == NULL)
- return -1;
-
- for (key = PyIter_Next(iter); key; key = PyIter_Next(iter)) {
- if (!override && PyDict_GetItem(a, key) != NULL) {
- Py_DECREF(key);
- continue;
- }
- value = PyObject_GetItem(b, key);
- if (value == NULL) {
- Py_DECREF(iter);
- Py_DECREF(key);
- return -1;
- }
- status = PyDict_SetItem(a, key, value);
- Py_DECREF(key);
- Py_DECREF(value);
- if (status < 0) {
- Py_DECREF(iter);
- return -1;
- }
- }
- Py_DECREF(iter);
- if (PyErr_Occurred())
- /* Iterator completed, via error */
- return -1;
- }
- return 0;
-}
-
-static PyObject *
-dict_copy(register dictobject *mp)
-{
- return PyDict_Copy((PyObject*)mp);
-}
-
-PyObject *
-PyDict_Copy(PyObject *o)
-{
- PyObject *copy;
-
- if (o == NULL || !PyDict_Check(o)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- copy = PyDict_New();
- if (copy == NULL)
- return NULL;
- if (PyDict_Merge(copy, o, 1) == 0)
- return copy;
- Py_DECREF(copy);
- return NULL;
-}
-
-Py_ssize_t
-PyDict_Size(PyObject *mp)
-{
- if (mp == NULL || !PyDict_Check(mp)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return ((dictobject *)mp)->ma_used;
-}
-
-PyObject *
-PyDict_Keys(PyObject *mp)
-{
- if (mp == NULL || !PyDict_Check(mp)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return dict_keys((dictobject *)mp);
-}
-
-PyObject *
-PyDict_Values(PyObject *mp)
-{
- if (mp == NULL || !PyDict_Check(mp)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return dict_values((dictobject *)mp);
-}
-
-PyObject *
-PyDict_Items(PyObject *mp)
-{
- if (mp == NULL || !PyDict_Check(mp)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return dict_items((dictobject *)mp);
-}
-
-/* Subroutine which returns the smallest key in a for which b's value
- is different or absent. The value is returned too, through the
- pval argument. Both are NULL if no key in a is found for which b's status
- differs. The refcounts on (and only on) non-NULL *pval and function return
- values must be decremented by the caller (characterize() increments them
- to ensure that mutating comparison and PyDict_GetItem calls can't delete
- them before the caller is done looking at them). */
-
-static PyObject *
-characterize(dictobject *a, dictobject *b, PyObject **pval)
-{
- PyObject *akey = NULL; /* smallest key in a s.t. a[akey] != b[akey] */
- PyObject *aval = NULL; /* a[akey] */
- Py_ssize_t i;
- int cmp;
-
- for (i = 0; i <= a->ma_mask; i++) {
- PyObject *thiskey, *thisaval, *thisbval;
- if (a->ma_table[i].me_value == NULL)
- continue;
- thiskey = a->ma_table[i].me_key;
- Py_INCREF(thiskey); /* keep alive across compares */
- if (akey != NULL) {
- cmp = PyObject_RichCompareBool(akey, thiskey, Py_LT);
- if (cmp < 0) {
- Py_DECREF(thiskey);
- goto Fail;
- }
- if (cmp > 0 ||
- i > a->ma_mask ||
- a->ma_table[i].me_value == NULL)
- {
- /* Not the *smallest* a key; or maybe it is
- * but the compare shrunk the dict so we can't
- * find its associated value anymore; or
- * maybe it is but the compare deleted the
- * a[thiskey] entry.
- */
- Py_DECREF(thiskey);
- continue;
- }
- }
-
- /* Compare a[thiskey] to b[thiskey]; cmp <- true iff equal. */
- thisaval = a->ma_table[i].me_value;
- assert(thisaval);
- Py_INCREF(thisaval); /* keep alive */
- thisbval = PyDict_GetItem((PyObject *)b, thiskey);
- if (thisbval == NULL)
- cmp = 0;
- else {
- /* both dicts have thiskey: same values? */
- cmp = PyObject_RichCompareBool(
- thisaval, thisbval, Py_EQ);
- if (cmp < 0) {
- Py_DECREF(thiskey);
- Py_DECREF(thisaval);
- goto Fail;
- }
- }
- if (cmp == 0) {
- /* New winner. */
- Py_XDECREF(akey);
- Py_XDECREF(aval);
- akey = thiskey;
- aval = thisaval;
- }
- else {
- Py_DECREF(thiskey);
- Py_DECREF(thisaval);
- }
- }
- *pval = aval;
- return akey;
-
-Fail:
- Py_XDECREF(akey);
- Py_XDECREF(aval);
- *pval = NULL;
- return NULL;
-}
-
-static int
-dict_compare(dictobject *a, dictobject *b)
-{
- PyObject *adiff, *bdiff, *aval, *bval;
- int res;
-
- /* Compare lengths first */
- if (a->ma_used < b->ma_used)
- return -1; /* a is shorter */
- else if (a->ma_used > b->ma_used)
- return 1; /* b is shorter */
-
- /* Same length -- check all keys */
- bdiff = bval = NULL;
- adiff = characterize(a, b, &aval);
- if (adiff == NULL) {
- assert(!aval);
- /* Either an error, or a is a subset with the same length so
- * must be equal.
- */
- res = PyErr_Occurred() ? -1 : 0;
- goto Finished;
- }
- bdiff = characterize(b, a, &bval);
- if (bdiff == NULL && PyErr_Occurred()) {
- assert(!bval);
- res = -1;
- goto Finished;
- }
- res = 0;
- if (bdiff) {
- /* bdiff == NULL "should be" impossible now, but perhaps
- * the last comparison done by the characterize() on a had
- * the side effect of making the dicts equal!
- */
- res = PyObject_Compare(adiff, bdiff);
- }
- if (res == 0 && bval != NULL)
- res = PyObject_Compare(aval, bval);
-
-Finished:
- Py_XDECREF(adiff);
- Py_XDECREF(bdiff);
- Py_XDECREF(aval);
- Py_XDECREF(bval);
- return res;
-}
-
-/* Return 1 if dicts equal, 0 if not, -1 if error.
- * Gets out as soon as any difference is detected.
- * Uses only Py_EQ comparison.
- */
-static int
-dict_equal(dictobject *a, dictobject *b)
-{
- Py_ssize_t i;
-
- if (a->ma_used != b->ma_used)
- /* can't be equal if # of entries differ */
- return 0;
-
- /* Same # of entries -- check all of 'em. Exit early on any diff. */
- for (i = 0; i <= a->ma_mask; i++) {
- PyObject *aval = a->ma_table[i].me_value;
- if (aval != NULL) {
- int cmp;
- PyObject *bval;
- PyObject *key = a->ma_table[i].me_key;
- /* temporarily bump aval's refcount to ensure it stays
- alive until we're done with it */
- Py_INCREF(aval);
- /* ditto for key */
- Py_INCREF(key);
- bval = PyDict_GetItem((PyObject *)b, key);
- Py_DECREF(key);
- if (bval == NULL) {
- Py_DECREF(aval);
- return 0;
- }
- cmp = PyObject_RichCompareBool(aval, bval, Py_EQ);
- Py_DECREF(aval);
- if (cmp <= 0) /* error or not equal */
- return cmp;
- }
- }
- return 1;
- }
-
-static PyObject *
-dict_richcompare(PyObject *v, PyObject *w, int op)
-{
- int cmp;
- PyObject *res;
-
- if (!PyDict_Check(v) || !PyDict_Check(w)) {
- res = Py_NotImplemented;
- }
- else if (op == Py_EQ || op == Py_NE) {
- cmp = dict_equal((dictobject *)v, (dictobject *)w);
- if (cmp < 0)
- return NULL;
- res = (cmp == (op == Py_EQ)) ? Py_True : Py_False;
- }
- else
- res = Py_NotImplemented;
- Py_INCREF(res);
- return res;
- }
-
-static PyObject *
-dict_has_key(register dictobject *mp, PyObject *key)
-{
- long hash;
- dictentry *ep;
-
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return NULL;
- }
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep == NULL)
- return NULL;
- return PyBool_FromLong(ep->me_value != NULL);
-}
-
-static PyObject *
-dict_get(register dictobject *mp, PyObject *args)
-{
- PyObject *key;
- PyObject *failobj = Py_None;
- PyObject *val = NULL;
- long hash;
- dictentry *ep;
-
- if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &failobj))
- return NULL;
-
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return NULL;
- }
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep == NULL)
- return NULL;
- val = ep->me_value;
- if (val == NULL)
- val = failobj;
- Py_INCREF(val);
- return val;
-}
-
-
-static PyObject *
-dict_setdefault(register dictobject *mp, PyObject *args)
-{
- PyObject *key;
- PyObject *failobj = Py_None;
- PyObject *val = NULL;
- long hash;
- dictentry *ep;
-
- if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &key, &failobj))
- return NULL;
-
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return NULL;
- }
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep == NULL)
- return NULL;
- val = ep->me_value;
- if (val == NULL) {
- val = failobj;
- if (PyDict_SetItem((PyObject*)mp, key, failobj))
- val = NULL;
- }
- Py_XINCREF(val);
- return val;
-}
-
-
-static PyObject *
-dict_clear(register dictobject *mp)
-{
- PyDict_Clear((PyObject *)mp);
- Py_RETURN_NONE;
-}
-
-static PyObject *
-dict_pop(dictobject *mp, PyObject *args)
-{
- long hash;
- dictentry *ep;
- PyObject *old_value, *old_key;
- PyObject *key, *deflt = NULL;
-
- if(!PyArg_UnpackTuple(args, "pop", 1, 2, &key, &deflt))
- return NULL;
- if (mp->ma_used == 0) {
- if (deflt) {
- Py_INCREF(deflt);
- return deflt;
- }
- PyErr_SetString(PyExc_KeyError,
- "pop(): dictionary is empty");
- return NULL;
- }
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return NULL;
- }
- ep = (mp->ma_lookup)(mp, key, hash);
- if (ep == NULL)
- return NULL;
- if (ep->me_value == NULL) {
- if (deflt) {
- Py_INCREF(deflt);
- return deflt;
- }
- set_key_error(key);
- return NULL;
- }
- old_key = ep->me_key;
- Py_INCREF(dummy);
- ep->me_key = dummy;
- old_value = ep->me_value;
- ep->me_value = NULL;
- mp->ma_used--;
- Py_DECREF(old_key);
- return old_value;
-}
-
-static PyObject *
-dict_popitem(dictobject *mp)
-{
- Py_ssize_t i = 0;
- dictentry *ep;
- PyObject *res;
-
- /* Allocate the result tuple before checking the size. Believe it
- * or not, this allocation could trigger a garbage collection which
- * could empty the dict, so if we checked the size first and that
- * happened, the result would be an infinite loop (searching for an
- * entry that no longer exists). Note that the usual popitem()
- * idiom is "while d: k, v = d.popitem()". so needing to throw the
- * tuple away if the dict *is* empty isn't a significant
- * inefficiency -- possible, but unlikely in practice.
- */
- res = PyTuple_New(2);
- if (res == NULL)
- return NULL;
- if (mp->ma_used == 0) {
- Py_DECREF(res);
- PyErr_SetString(PyExc_KeyError,
- "popitem(): dictionary is empty");
- return NULL;
- }
- /* Set ep to "the first" dict entry with a value. We abuse the hash
- * field of slot 0 to hold a search finger:
- * If slot 0 has a value, use slot 0.
- * Else slot 0 is being used to hold a search finger,
- * and we use its hash value as the first index to look.
- */
- ep = &mp->ma_table[0];
- if (ep->me_value == NULL) {
- i = ep->me_hash;
- /* The hash field may be a real hash value, or it may be a
- * legit search finger, or it may be a once-legit search
- * finger that's out of bounds now because it wrapped around
- * or the table shrunk -- simply make sure it's in bounds now.
- */
- if (i > mp->ma_mask || i < 1)
- i = 1; /* skip slot 0 */
- while ((ep = &mp->ma_table[i])->me_value == NULL) {
- i++;
- if (i > mp->ma_mask)
- i = 1;
- }
- }
- PyTuple_SET_ITEM(res, 0, ep->me_key);
- PyTuple_SET_ITEM(res, 1, ep->me_value);
- Py_INCREF(dummy);
- ep->me_key = dummy;
- ep->me_value = NULL;
- mp->ma_used--;
- assert(mp->ma_table[0].me_value == NULL);
- mp->ma_table[0].me_hash = i + 1; /* next place to start */
- return res;
-}
-
-static int
-dict_traverse(PyObject *op, visitproc visit, void *arg)
-{
- Py_ssize_t i = 0;
- PyObject *pk;
- PyObject *pv;
-
- while (PyDict_Next(op, &i, &pk, &pv)) {
- Py_VISIT(pk);
- Py_VISIT(pv);
- }
- return 0;
-}
-
-static int
-dict_tp_clear(PyObject *op)
-{
- PyDict_Clear(op);
- return 0;
-}
-
-
-extern PyTypeObject PyDictIterKey_Type; /* Forward */
-extern PyTypeObject PyDictIterValue_Type; /* Forward */
-extern PyTypeObject PyDictIterItem_Type; /* Forward */
-static PyObject *dictiter_new(dictobject *, PyTypeObject *);
-
-static PyObject *
-dict_iterkeys(dictobject *dict)
-{
- return dictiter_new(dict, &PyDictIterKey_Type);
-}
-
-static PyObject *
-dict_itervalues(dictobject *dict)
-{
- return dictiter_new(dict, &PyDictIterValue_Type);
-}
-
-static PyObject *
-dict_iteritems(dictobject *dict)
-{
- return dictiter_new(dict, &PyDictIterItem_Type);
-}
-
-
-PyDoc_STRVAR(has_key__doc__,
-"D.has_key(k) -> True if D has a key k, else False");
-
-PyDoc_STRVAR(contains__doc__,
-"D.__contains__(k) -> True if D has a key k, else False");
-
-PyDoc_STRVAR(getitem__doc__, "x.__getitem__(y) <==> x[y]");
-
-PyDoc_STRVAR(get__doc__,
-"D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.");
-
-PyDoc_STRVAR(setdefault_doc__,
-"D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D");
-
-PyDoc_STRVAR(pop__doc__,
-"D.pop(k[,d]) -> v, remove specified key and return the corresponding value\n\
-If key is not found, d is returned if given, otherwise KeyError is raised");
-
-PyDoc_STRVAR(popitem__doc__,
-"D.popitem() -> (k, v), remove and return some (key, value) pair as a\n\
-2-tuple; but raise KeyError if D is empty");
-
-PyDoc_STRVAR(keys__doc__,
-"D.keys() -> list of D's keys");
-
-PyDoc_STRVAR(items__doc__,
-"D.items() -> list of D's (key, value) pairs, as 2-tuples");
-
-PyDoc_STRVAR(values__doc__,
-"D.values() -> list of D's values");
-
-PyDoc_STRVAR(update__doc__,
-"D.update(E, **F) -> None. Update D from E and F: for k in E: D[k] = E[k]\n\
-(if E has keys else: for (k, v) in E: D[k] = v) then: for k in F: D[k] = F[k]");
-
-PyDoc_STRVAR(fromkeys__doc__,
-"dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.\n\
-v defaults to None.");
-
-PyDoc_STRVAR(clear__doc__,
-"D.clear() -> None. Remove all items from D.");
-
-PyDoc_STRVAR(copy__doc__,
-"D.copy() -> a shallow copy of D");
-
-PyDoc_STRVAR(iterkeys__doc__,
-"D.iterkeys() -> an iterator over the keys of D");
-
-PyDoc_STRVAR(itervalues__doc__,
-"D.itervalues() -> an iterator over the values of D");
-
-PyDoc_STRVAR(iteritems__doc__,
-"D.iteritems() -> an iterator over the (key, value) items of D");
-
-static PyMethodDef mapp_methods[] = {
- {"__contains__",(PyCFunction)dict_has_key, METH_O | METH_COEXIST,
- contains__doc__},
- {"__getitem__", (PyCFunction)dict_subscript, METH_O | METH_COEXIST,
- getitem__doc__},
- {"has_key", (PyCFunction)dict_has_key, METH_O,
- has_key__doc__},
- {"get", (PyCFunction)dict_get, METH_VARARGS,
- get__doc__},
- {"setdefault", (PyCFunction)dict_setdefault, METH_VARARGS,
- setdefault_doc__},
- {"pop", (PyCFunction)dict_pop, METH_VARARGS,
- pop__doc__},
- {"popitem", (PyCFunction)dict_popitem, METH_NOARGS,
- popitem__doc__},
- {"keys", (PyCFunction)dict_keys, METH_NOARGS,
- keys__doc__},
- {"items", (PyCFunction)dict_items, METH_NOARGS,
- items__doc__},
- {"values", (PyCFunction)dict_values, METH_NOARGS,
- values__doc__},
- {"update", (PyCFunction)dict_update, METH_VARARGS | METH_KEYWORDS,
- update__doc__},
- {"fromkeys", (PyCFunction)dict_fromkeys, METH_VARARGS | METH_CLASS,
- fromkeys__doc__},
- {"clear", (PyCFunction)dict_clear, METH_NOARGS,
- clear__doc__},
- {"copy", (PyCFunction)dict_copy, METH_NOARGS,
- copy__doc__},
- {"iterkeys", (PyCFunction)dict_iterkeys, METH_NOARGS,
- iterkeys__doc__},
- {"itervalues", (PyCFunction)dict_itervalues, METH_NOARGS,
- itervalues__doc__},
- {"iteritems", (PyCFunction)dict_iteritems, METH_NOARGS,
- iteritems__doc__},
- {NULL, NULL} /* sentinel */
-};
-
-/* Return 1 if `key` is in dict `op`, 0 if not, and -1 on error. */
-int
-PyDict_Contains(PyObject *op, PyObject *key)
-{
- long hash;
- dictobject *mp = (dictobject *)op;
- dictentry *ep;
-
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return -1;
- }
- ep = (mp->ma_lookup)(mp, key, hash);
- return ep == NULL ? -1 : (ep->me_value != NULL);
-}
-
-/* Internal version of PyDict_Contains used when the hash value is already known */
-int
-_PyDict_Contains(PyObject *op, PyObject *key, long hash)
-{
- dictobject *mp = (dictobject *)op;
- dictentry *ep;
-
- ep = (mp->ma_lookup)(mp, key, hash);
- return ep == NULL ? -1 : (ep->me_value != NULL);
-}
-
-/* Hack to implement "key in dict" */
-static PySequenceMethods dict_as_sequence = {
- 0, /* sq_length */
- 0, /* sq_concat */
- 0, /* sq_repeat */
- 0, /* sq_item */
- 0, /* sq_slice */
- 0, /* sq_ass_item */
- 0, /* sq_ass_slice */
- PyDict_Contains, /* sq_contains */
- 0, /* sq_inplace_concat */
- 0, /* sq_inplace_repeat */
-};
-
-static PyObject *
-dict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *self;
-
- assert(type != NULL && type->tp_alloc != NULL);
- self = type->tp_alloc(type, 0);
- if (self != NULL) {
- PyDictObject *d = (PyDictObject *)self;
- /* It's guaranteed that tp->alloc zeroed out the struct. */
- assert(d->ma_table == NULL && d->ma_fill == 0 && d->ma_used == 0);
- INIT_NONZERO_DICT_SLOTS(d);
- d->ma_lookup = lookdict_string;
-#ifdef SHOW_CONVERSION_COUNTS
- ++created;
-#endif
- }
- return self;
-}
-
-static int
-dict_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- return dict_update_common(self, args, kwds, "dict");
-}
-
-static long
-dict_nohash(PyObject *self)
-{
- PyErr_SetString(PyExc_TypeError, "dict objects are unhashable");
- return -1;
-}
-
-static PyObject *
-dict_iter(dictobject *dict)
-{
- return dictiter_new(dict, &PyDictIterKey_Type);
-}
-
-PyDoc_STRVAR(dictionary_doc,
-"dict() -> new empty dictionary.\n"
-"dict(mapping) -> new dictionary initialized from a mapping object's\n"
-" (key, value) pairs.\n"
-"dict(seq) -> new dictionary initialized as if via:\n"
-" d = {}\n"
-" for k, v in seq:\n"
-" d[k] = v\n"
-"dict(**kwargs) -> new dictionary initialized with the name=value pairs\n"
-" in the keyword argument list. For example: dict(one=1, two=2)");
-
-PyTypeObject PyDict_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "dict",
- sizeof(dictobject),
- 0,
- (destructor)dict_dealloc, /* tp_dealloc */
- (printfunc)dict_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)dict_compare, /* tp_compare */
- (reprfunc)dict_repr, /* tp_repr */
- 0, /* tp_as_number */
- &dict_as_sequence, /* tp_as_sequence */
- &dict_as_mapping, /* tp_as_mapping */
- dict_nohash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- dictionary_doc, /* tp_doc */
- dict_traverse, /* tp_traverse */
- dict_tp_clear, /* tp_clear */
- dict_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- (getiterfunc)dict_iter, /* tp_iter */
- 0, /* tp_iternext */
- mapp_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- dict_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- dict_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-/* For backward compatibility with old dictionary interface */
-
-PyObject *
-PyDict_GetItemString(PyObject *v, const char *key)
-{
- PyObject *kv, *rv;
- kv = PyString_FromString(key);
- if (kv == NULL)
- return NULL;
- rv = PyDict_GetItem(v, kv);
- Py_DECREF(kv);
- return rv;
-}
-
-int
-PyDict_SetItemString(PyObject *v, const char *key, PyObject *item)
-{
- PyObject *kv;
- int err;
- kv = PyString_FromString(key);
- if (kv == NULL)
- return -1;
- PyString_InternInPlace(&kv); /* XXX Should we really? */
- err = PyDict_SetItem(v, kv, item);
- Py_DECREF(kv);
- return err;
-}
-
-int
-PyDict_DelItemString(PyObject *v, const char *key)
-{
- PyObject *kv;
- int err;
- kv = PyString_FromString(key);
- if (kv == NULL)
- return -1;
- err = PyDict_DelItem(v, kv);
- Py_DECREF(kv);
- return err;
-}
-
-/* Dictionary iterator types */
-
-typedef struct {
- PyObject_HEAD
- dictobject *di_dict; /* Set to NULL when iterator is exhausted */
- Py_ssize_t di_used;
- Py_ssize_t di_pos;
- PyObject* di_result; /* reusable result tuple for iteritems */
- Py_ssize_t len;
-} dictiterobject;
-
-static PyObject *
-dictiter_new(dictobject *dict, PyTypeObject *itertype)
-{
- dictiterobject *di;
- di = PyObject_New(dictiterobject, itertype);
- if (di == NULL)
- return NULL;
- Py_INCREF(dict);
- di->di_dict = dict;
- di->di_used = dict->ma_used;
- di->di_pos = 0;
- di->len = dict->ma_used;
- if (itertype == &PyDictIterItem_Type) {
- di->di_result = PyTuple_Pack(2, Py_None, Py_None);
- if (di->di_result == NULL) {
- Py_DECREF(di);
- return NULL;
- }
- }
- else
- di->di_result = NULL;
- return (PyObject *)di;
-}
-
-static void
-dictiter_dealloc(dictiterobject *di)
-{
- Py_XDECREF(di->di_dict);
- Py_XDECREF(di->di_result);
- PyObject_Del(di);
-}
-
-static PyObject *
-dictiter_len(dictiterobject *di)
-{
- Py_ssize_t len = 0;
- if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)
- len = di->len;
- return PyInt_FromSize_t(len);
-}
-
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
-
-static PyMethodDef dictiter_methods[] = {
- {"__length_hint__", (PyCFunction)dictiter_len, METH_NOARGS, length_hint_doc},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *dictiter_iternextkey(dictiterobject *di)
-{
- PyObject *key;
- register Py_ssize_t i, mask;
- register dictentry *ep;
- dictobject *d = di->di_dict;
-
- if (d == NULL)
- return NULL;
- assert (PyDict_Check(d));
-
- if (di->di_used != d->ma_used) {
- PyErr_SetString(PyExc_RuntimeError,
- "dictionary changed size during iteration");
- di->di_used = -1; /* Make this state sticky */
- return NULL;
- }
-
- i = di->di_pos;
- if (i < 0)
- goto fail;
- ep = d->ma_table;
- mask = d->ma_mask;
- while (i <= mask && ep[i].me_value == NULL)
- i++;
- di->di_pos = i+1;
- if (i > mask)
- goto fail;
- di->len--;
- key = ep[i].me_key;
- Py_INCREF(key);
- return key;
-
-fail:
- Py_DECREF(d);
- di->di_dict = NULL;
- return NULL;
-}
-
-PyTypeObject PyDictIterKey_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "dictionary-keyiterator", /* tp_name */
- sizeof(dictiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)dictiter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)dictiter_iternextkey, /* tp_iternext */
- dictiter_methods, /* tp_methods */
- 0,
-};
-
-static PyObject *dictiter_iternextvalue(dictiterobject *di)
-{
- PyObject *value;
- register Py_ssize_t i, mask;
- register dictentry *ep;
- dictobject *d = di->di_dict;
-
- if (d == NULL)
- return NULL;
- assert (PyDict_Check(d));
-
- if (di->di_used != d->ma_used) {
- PyErr_SetString(PyExc_RuntimeError,
- "dictionary changed size during iteration");
- di->di_used = -1; /* Make this state sticky */
- return NULL;
- }
-
- i = di->di_pos;
- mask = d->ma_mask;
- if (i < 0 || i > mask)
- goto fail;
- ep = d->ma_table;
- while ((value=ep[i].me_value) == NULL) {
- i++;
- if (i > mask)
- goto fail;
- }
- di->di_pos = i+1;
- di->len--;
- Py_INCREF(value);
- return value;
-
-fail:
- Py_DECREF(d);
- di->di_dict = NULL;
- return NULL;
-}
-
-PyTypeObject PyDictIterValue_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "dictionary-valueiterator", /* tp_name */
- sizeof(dictiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)dictiter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)dictiter_iternextvalue, /* tp_iternext */
- dictiter_methods, /* tp_methods */
- 0,
-};
-
-static PyObject *dictiter_iternextitem(dictiterobject *di)
-{
- PyObject *key, *value, *result = di->di_result;
- register Py_ssize_t i, mask;
- register dictentry *ep;
- dictobject *d = di->di_dict;
-
- if (d == NULL)
- return NULL;
- assert (PyDict_Check(d));
-
- if (di->di_used != d->ma_used) {
- PyErr_SetString(PyExc_RuntimeError,
- "dictionary changed size during iteration");
- di->di_used = -1; /* Make this state sticky */
- return NULL;
- }
-
- i = di->di_pos;
- if (i < 0)
- goto fail;
- ep = d->ma_table;
- mask = d->ma_mask;
- while (i <= mask && ep[i].me_value == NULL)
- i++;
- di->di_pos = i+1;
- if (i > mask)
- goto fail;
-
- if (result->ob_refcnt == 1) {
- Py_INCREF(result);
- Py_DECREF(PyTuple_GET_ITEM(result, 0));
- Py_DECREF(PyTuple_GET_ITEM(result, 1));
- } else {
- result = PyTuple_New(2);
- if (result == NULL)
- return NULL;
- }
- di->len--;
- key = ep[i].me_key;
- value = ep[i].me_value;
- Py_INCREF(key);
- Py_INCREF(value);
- PyTuple_SET_ITEM(result, 0, key);
- PyTuple_SET_ITEM(result, 1, value);
- return result;
-
-fail:
- Py_DECREF(d);
- di->di_dict = NULL;
- return NULL;
-}
-
-PyTypeObject PyDictIterItem_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "dictionary-itemiterator", /* tp_name */
- sizeof(dictiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)dictiter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)dictiter_iternextitem, /* tp_iternext */
- dictiter_methods, /* tp_methods */
- 0,
-};
diff --git a/sys/src/cmd/python/Objects/enumobject.c b/sys/src/cmd/python/Objects/enumobject.c
deleted file mode 100644
index a456c9daf..000000000
--- a/sys/src/cmd/python/Objects/enumobject.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/* enumerate object */
-
-#include "Python.h"
-
-typedef struct {
- PyObject_HEAD
- long en_index; /* current index of enumeration */
- PyObject* en_sit; /* secondary iterator of enumeration */
- PyObject* en_result; /* result tuple */
-} enumobject;
-
-static PyObject *
-enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- enumobject *en;
- PyObject *seq = NULL;
- static char *kwlist[] = {"sequence", 0};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:enumerate", kwlist,
- &seq))
- return NULL;
-
- en = (enumobject *)type->tp_alloc(type, 0);
- if (en == NULL)
- return NULL;
- en->en_index = 0;
- en->en_sit = PyObject_GetIter(seq);
- if (en->en_sit == NULL) {
- Py_DECREF(en);
- return NULL;
- }
- en->en_result = PyTuple_Pack(2, Py_None, Py_None);
- if (en->en_result == NULL) {
- Py_DECREF(en);
- return NULL;
- }
- return (PyObject *)en;
-}
-
-static void
-enum_dealloc(enumobject *en)
-{
- PyObject_GC_UnTrack(en);
- Py_XDECREF(en->en_sit);
- Py_XDECREF(en->en_result);
- en->ob_type->tp_free(en);
-}
-
-static int
-enum_traverse(enumobject *en, visitproc visit, void *arg)
-{
- Py_VISIT(en->en_sit);
- Py_VISIT(en->en_result);
- return 0;
-}
-
-static PyObject *
-enum_next(enumobject *en)
-{
- PyObject *next_index;
- PyObject *next_item;
- PyObject *result = en->en_result;
- PyObject *it = en->en_sit;
-
- if (en->en_index == LONG_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "enumerate() is limited to LONG_MAX items");
- return NULL;
- }
-
- next_item = (*it->ob_type->tp_iternext)(it);
- if (next_item == NULL)
- return NULL;
-
- next_index = PyInt_FromLong(en->en_index);
- if (next_index == NULL) {
- Py_DECREF(next_item);
- return NULL;
- }
- en->en_index++;
-
- if (result->ob_refcnt == 1) {
- Py_INCREF(result);
- Py_DECREF(PyTuple_GET_ITEM(result, 0));
- Py_DECREF(PyTuple_GET_ITEM(result, 1));
- } else {
- result = PyTuple_New(2);
- if (result == NULL) {
- Py_DECREF(next_index);
- Py_DECREF(next_item);
- return NULL;
- }
- }
- PyTuple_SET_ITEM(result, 0, next_index);
- PyTuple_SET_ITEM(result, 1, next_item);
- return result;
-}
-
-PyDoc_STRVAR(enum_doc,
-"enumerate(iterable) -> iterator for index, value of iterable\n"
-"\n"
-"Return an enumerate object. iterable must be an other object that supports\n"
-"iteration. The enumerate object yields pairs containing a count (from\n"
-"zero) and a value yielded by the iterable argument. enumerate is useful\n"
-"for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");
-
-PyTypeObject PyEnum_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "enumerate", /* tp_name */
- sizeof(enumobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)enum_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- enum_doc, /* tp_doc */
- (traverseproc)enum_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)enum_next, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- enum_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-/* Reversed Object ***************************************************************/
-
-typedef struct {
- PyObject_HEAD
- Py_ssize_t index;
- PyObject* seq;
-} reversedobject;
-
-static PyObject *
-reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- Py_ssize_t n;
- PyObject *seq;
- reversedobject *ro;
-
- if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq))
- return NULL;
-
- if (PyObject_HasAttrString(seq, "__reversed__"))
- return PyObject_CallMethod(seq, "__reversed__", NULL);
-
- if (!PySequence_Check(seq)) {
- PyErr_SetString(PyExc_TypeError,
- "argument to reversed() must be a sequence");
- return NULL;
- }
-
- n = PySequence_Size(seq);
- if (n == -1)
- return NULL;
-
- ro = (reversedobject *)type->tp_alloc(type, 0);
- if (ro == NULL)
- return NULL;
-
- ro->index = n-1;
- Py_INCREF(seq);
- ro->seq = seq;
- return (PyObject *)ro;
-}
-
-static void
-reversed_dealloc(reversedobject *ro)
-{
- PyObject_GC_UnTrack(ro);
- Py_XDECREF(ro->seq);
- ro->ob_type->tp_free(ro);
-}
-
-static int
-reversed_traverse(reversedobject *ro, visitproc visit, void *arg)
-{
- Py_VISIT(ro->seq);
- return 0;
-}
-
-static PyObject *
-reversed_next(reversedobject *ro)
-{
- PyObject *item;
- Py_ssize_t index = ro->index;
-
- if (index >= 0) {
- item = PySequence_GetItem(ro->seq, index);
- if (item != NULL) {
- ro->index--;
- return item;
- }
- if (PyErr_ExceptionMatches(PyExc_IndexError) ||
- PyErr_ExceptionMatches(PyExc_StopIteration))
- PyErr_Clear();
- }
- ro->index = -1;
- Py_CLEAR(ro->seq);
- return NULL;
-}
-
-PyDoc_STRVAR(reversed_doc,
-"reversed(sequence) -> reverse iterator over values of the sequence\n"
-"\n"
-"Return a reverse iterator");
-
-static PyObject *
-reversed_len(reversedobject *ro)
-{
- Py_ssize_t position, seqsize;
-
- if (ro->seq == NULL)
- return PyInt_FromLong(0);
- seqsize = PySequence_Size(ro->seq);
- if (seqsize == -1)
- return NULL;
- position = ro->index + 1;
- return PyInt_FromSsize_t((seqsize < position) ? 0 : position);
-}
-
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
-
-static PyMethodDef reversediter_methods[] = {
- {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},
- {NULL, NULL} /* sentinel */
-};
-
-PyTypeObject PyReversed_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "reversed", /* tp_name */
- sizeof(reversedobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)reversed_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- reversed_doc, /* tp_doc */
- (traverseproc)reversed_traverse,/* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)reversed_next, /* tp_iternext */
- reversediter_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- reversed_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
diff --git a/sys/src/cmd/python/Objects/exceptions.c b/sys/src/cmd/python/Objects/exceptions.c
deleted file mode 100644
index 0cd819c5a..000000000
--- a/sys/src/cmd/python/Objects/exceptions.c
+++ /dev/null
@@ -1,2147 +0,0 @@
-/*
- * New exceptions.c written in Iceland by Richard Jones and Georg Brandl.
- *
- * Thanks go to Tim Peters and Michael Hudson for debugging.
- */
-
-#define PY_SSIZE_T_CLEAN
-#include <Python.h>
-#include "structmember.h"
-#include "osdefs.h"
-
-#define MAKE_IT_NONE(x) (x) = Py_None; Py_INCREF(Py_None);
-#define EXC_MODULE_NAME "exceptions."
-
-/* NOTE: If the exception class hierarchy changes, don't forget to update
- * Lib/test/exception_hierarchy.txt
- */
-
-PyDoc_STRVAR(exceptions_doc, "Python's standard exception class hierarchy.\n\
-\n\
-Exceptions found here are defined both in the exceptions module and the\n\
-built-in namespace. It is recommended that user-defined exceptions\n\
-inherit from Exception. See the documentation for the exception\n\
-inheritance hierarchy.\n\
-");
-
-/*
- * BaseException
- */
-static PyObject *
-BaseException_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyBaseExceptionObject *self;
-
- self = (PyBaseExceptionObject *)type->tp_alloc(type, 0);
- /* the dict is created on the fly in PyObject_GenericSetAttr */
- self->message = self->dict = NULL;
-
- self->args = PyTuple_New(0);
- if (!self->args) {
- Py_DECREF(self);
- return NULL;
- }
-
- self->message = PyString_FromString("");
- if (!self->message) {
- Py_DECREF(self);
- return NULL;
- }
-
- return (PyObject *)self;
-}
-
-static int
-BaseException_init(PyBaseExceptionObject *self, PyObject *args, PyObject *kwds)
-{
- if (!_PyArg_NoKeywords(self->ob_type->tp_name, kwds))
- return -1;
-
- Py_DECREF(self->args);
- self->args = args;
- Py_INCREF(self->args);
-
- if (PyTuple_GET_SIZE(self->args) == 1) {
- Py_CLEAR(self->message);
- self->message = PyTuple_GET_ITEM(self->args, 0);
- Py_INCREF(self->message);
- }
- return 0;
-}
-
-static int
-BaseException_clear(PyBaseExceptionObject *self)
-{
- Py_CLEAR(self->dict);
- Py_CLEAR(self->args);
- Py_CLEAR(self->message);
- return 0;
-}
-
-static void
-BaseException_dealloc(PyBaseExceptionObject *self)
-{
- _PyObject_GC_UNTRACK(self);
- BaseException_clear(self);
- self->ob_type->tp_free((PyObject *)self);
-}
-
-static int
-BaseException_traverse(PyBaseExceptionObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->dict);
- Py_VISIT(self->args);
- Py_VISIT(self->message);
- return 0;
-}
-
-static PyObject *
-BaseException_str(PyBaseExceptionObject *self)
-{
- PyObject *out;
-
- switch (PyTuple_GET_SIZE(self->args)) {
- case 0:
- out = PyString_FromString("");
- break;
- case 1:
- out = PyObject_Str(PyTuple_GET_ITEM(self->args, 0));
- break;
- default:
- out = PyObject_Str(self->args);
- break;
- }
-
- return out;
-}
-
-static PyObject *
-BaseException_repr(PyBaseExceptionObject *self)
-{
- PyObject *repr_suffix;
- PyObject *repr;
- char *name;
- char *dot;
-
- repr_suffix = PyObject_Repr(self->args);
- if (!repr_suffix)
- return NULL;
-
- name = (char *)self->ob_type->tp_name;
- dot = strrchr(name, '.');
- if (dot != NULL) name = dot+1;
-
- repr = PyString_FromString(name);
- if (!repr) {
- Py_DECREF(repr_suffix);
- return NULL;
- }
-
- PyString_ConcatAndDel(&repr, repr_suffix);
- return repr;
-}
-
-/* Pickling support */
-static PyObject *
-BaseException_reduce(PyBaseExceptionObject *self)
-{
- if (self->args && self->dict)
- return PyTuple_Pack(3, self->ob_type, self->args, self->dict);
- else
- return PyTuple_Pack(2, self->ob_type, self->args);
-}
-
-/*
- * Needed for backward compatibility, since exceptions used to store
- * all their attributes in the __dict__. Code is taken from cPickle's
- * load_build function.
- */
-static PyObject *
-BaseException_setstate(PyObject *self, PyObject *state)
-{
- PyObject *d_key, *d_value;
- Py_ssize_t i = 0;
-
- if (state != Py_None) {
- if (!PyDict_Check(state)) {
- PyErr_SetString(PyExc_TypeError, "state is not a dictionary");
- return NULL;
- }
- while (PyDict_Next(state, &i, &d_key, &d_value)) {
- if (PyObject_SetAttr(self, d_key, d_value) < 0)
- return NULL;
- }
- }
- Py_RETURN_NONE;
-}
-
-
-static PyMethodDef BaseException_methods[] = {
- {"__reduce__", (PyCFunction)BaseException_reduce, METH_NOARGS },
- {"__setstate__", (PyCFunction)BaseException_setstate, METH_O },
- {NULL, NULL, 0, NULL},
-};
-
-
-
-static PyObject *
-BaseException_getitem(PyBaseExceptionObject *self, Py_ssize_t index)
-{
- return PySequence_GetItem(self->args, index);
-}
-
-static PyObject *
-BaseException_getslice(PyBaseExceptionObject *self,
- Py_ssize_t start, Py_ssize_t stop)
-{
- return PySequence_GetSlice(self->args, start, stop);
-}
-
-static PySequenceMethods BaseException_as_sequence = {
- 0, /* sq_length; */
- 0, /* sq_concat; */
- 0, /* sq_repeat; */
- (ssizeargfunc)BaseException_getitem, /* sq_item; */
- (ssizessizeargfunc)BaseException_getslice, /* sq_slice; */
- 0, /* sq_ass_item; */
- 0, /* sq_ass_slice; */
- 0, /* sq_contains; */
- 0, /* sq_inplace_concat; */
- 0 /* sq_inplace_repeat; */
-};
-
-static PyMemberDef BaseException_members[] = {
- {"message", T_OBJECT, offsetof(PyBaseExceptionObject, message), 0,
- PyDoc_STR("exception message")},
- {NULL} /* Sentinel */
-};
-
-
-static PyObject *
-BaseException_get_dict(PyBaseExceptionObject *self)
-{
- if (self->dict == NULL) {
- self->dict = PyDict_New();
- if (!self->dict)
- return NULL;
- }
- Py_INCREF(self->dict);
- return self->dict;
-}
-
-static int
-BaseException_set_dict(PyBaseExceptionObject *self, PyObject *val)
-{
- if (val == NULL) {
- PyErr_SetString(PyExc_TypeError, "__dict__ may not be deleted");
- return -1;
- }
- if (!PyDict_Check(val)) {
- PyErr_SetString(PyExc_TypeError, "__dict__ must be a dictionary");
- return -1;
- }
- Py_CLEAR(self->dict);
- Py_INCREF(val);
- self->dict = val;
- return 0;
-}
-
-static PyObject *
-BaseException_get_args(PyBaseExceptionObject *self)
-{
- if (self->args == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- Py_INCREF(self->args);
- return self->args;
-}
-
-static int
-BaseException_set_args(PyBaseExceptionObject *self, PyObject *val)
-{
- PyObject *seq;
- if (val == NULL) {
- PyErr_SetString(PyExc_TypeError, "args may not be deleted");
- return -1;
- }
- seq = PySequence_Tuple(val);
- if (!seq) return -1;
- Py_CLEAR(self->args);
- self->args = seq;
- return 0;
-}
-
-static PyGetSetDef BaseException_getset[] = {
- {"__dict__", (getter)BaseException_get_dict, (setter)BaseException_set_dict},
- {"args", (getter)BaseException_get_args, (setter)BaseException_set_args},
- {NULL},
-};
-
-
-static PyTypeObject _PyExc_BaseException = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- EXC_MODULE_NAME "BaseException", /*tp_name*/
- sizeof(PyBaseExceptionObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- (destructor)BaseException_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /* tp_compare; */
- (reprfunc)BaseException_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- &BaseException_as_sequence, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
- 0, /*tp_call*/
- (reprfunc)BaseException_str, /*tp_str*/
- PyObject_GenericGetAttr, /*tp_getattro*/
- PyObject_GenericSetAttr, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
- PyDoc_STR("Common base class for all exceptions"), /* tp_doc */
- (traverseproc)BaseException_traverse, /* tp_traverse */
- (inquiry)BaseException_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- BaseException_methods, /* tp_methods */
- BaseException_members, /* tp_members */
- BaseException_getset, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(PyBaseExceptionObject, dict), /* tp_dictoffset */
- (initproc)BaseException_init, /* tp_init */
- 0, /* tp_alloc */
- BaseException_new, /* tp_new */
-};
-/* the CPython API expects exceptions to be (PyObject *) - both a hold-over
-from the previous implmentation and also allowing Python objects to be used
-in the API */
-PyObject *PyExc_BaseException = (PyObject *)&_PyExc_BaseException;
-
-/* note these macros omit the last semicolon so the macro invocation may
- * include it and not look strange.
- */
-#define SimpleExtendsException(EXCBASE, EXCNAME, EXCDOC) \
-static PyTypeObject _PyExc_ ## EXCNAME = { \
- PyObject_HEAD_INIT(NULL) \
- 0, \
- EXC_MODULE_NAME # EXCNAME, \
- sizeof(PyBaseExceptionObject), \
- 0, (destructor)BaseException_dealloc, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, 0, 0, \
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
- PyDoc_STR(EXCDOC), (traverseproc)BaseException_traverse, \
- (inquiry)BaseException_clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
- 0, 0, 0, offsetof(PyBaseExceptionObject, dict), \
- (initproc)BaseException_init, 0, BaseException_new,\
-}; \
-PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
-
-#define MiddlingExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDOC) \
-static PyTypeObject _PyExc_ ## EXCNAME = { \
- PyObject_HEAD_INIT(NULL) \
- 0, \
- EXC_MODULE_NAME # EXCNAME, \
- sizeof(Py ## EXCSTORE ## Object), \
- 0, (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- 0, 0, 0, 0, 0, \
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
- PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
- (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, 0, 0, 0, &_ ## EXCBASE, \
- 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
- (initproc)EXCSTORE ## _init, 0, BaseException_new,\
-}; \
-PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
-
-#define ComplexExtendsException(EXCBASE, EXCNAME, EXCSTORE, EXCDEALLOC, EXCMETHODS, EXCMEMBERS, EXCSTR, EXCDOC) \
-static PyTypeObject _PyExc_ ## EXCNAME = { \
- PyObject_HEAD_INIT(NULL) \
- 0, \
- EXC_MODULE_NAME # EXCNAME, \
- sizeof(Py ## EXCSTORE ## Object), 0, \
- (destructor)EXCSTORE ## _dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- (reprfunc)EXCSTR, 0, 0, 0, \
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, \
- PyDoc_STR(EXCDOC), (traverseproc)EXCSTORE ## _traverse, \
- (inquiry)EXCSTORE ## _clear, 0, 0, 0, 0, EXCMETHODS, \
- EXCMEMBERS, 0, &_ ## EXCBASE, \
- 0, 0, 0, offsetof(Py ## EXCSTORE ## Object, dict), \
- (initproc)EXCSTORE ## _init, 0, BaseException_new,\
-}; \
-PyObject *PyExc_ ## EXCNAME = (PyObject *)&_PyExc_ ## EXCNAME
-
-
-/*
- * Exception extends BaseException
- */
-SimpleExtendsException(PyExc_BaseException, Exception,
- "Common base class for all non-exit exceptions.");
-
-
-/*
- * StandardError extends Exception
- */
-SimpleExtendsException(PyExc_Exception, StandardError,
- "Base class for all standard Python exceptions that do not represent\n"
- "interpreter exiting.");
-
-
-/*
- * TypeError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, TypeError,
- "Inappropriate argument type.");
-
-
-/*
- * StopIteration extends Exception
- */
-SimpleExtendsException(PyExc_Exception, StopIteration,
- "Signal the end from iterator.next().");
-
-
-/*
- * GeneratorExit extends Exception
- */
-SimpleExtendsException(PyExc_Exception, GeneratorExit,
- "Request that a generator exit.");
-
-
-/*
- * SystemExit extends BaseException
- */
-
-static int
-SystemExit_init(PySystemExitObject *self, PyObject *args, PyObject *kwds)
-{
- Py_ssize_t size = PyTuple_GET_SIZE(args);
-
- if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
- return -1;
-
- if (size == 0)
- return 0;
- Py_CLEAR(self->code);
- if (size == 1)
- self->code = PyTuple_GET_ITEM(args, 0);
- else if (size > 1)
- self->code = args;
- Py_INCREF(self->code);
- return 0;
-}
-
-static int
-SystemExit_clear(PySystemExitObject *self)
-{
- Py_CLEAR(self->code);
- return BaseException_clear((PyBaseExceptionObject *)self);
-}
-
-static void
-SystemExit_dealloc(PySystemExitObject *self)
-{
- _PyObject_GC_UNTRACK(self);
- SystemExit_clear(self);
- self->ob_type->tp_free((PyObject *)self);
-}
-
-static int
-SystemExit_traverse(PySystemExitObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->code);
- return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
-}
-
-static PyMemberDef SystemExit_members[] = {
- {"message", T_OBJECT, offsetof(PySystemExitObject, message), 0,
- PyDoc_STR("exception message")},
- {"code", T_OBJECT, offsetof(PySystemExitObject, code), 0,
- PyDoc_STR("exception code")},
- {NULL} /* Sentinel */
-};
-
-ComplexExtendsException(PyExc_BaseException, SystemExit, SystemExit,
- SystemExit_dealloc, 0, SystemExit_members, 0,
- "Request to exit from the interpreter.");
-
-/*
- * KeyboardInterrupt extends BaseException
- */
-SimpleExtendsException(PyExc_BaseException, KeyboardInterrupt,
- "Program interrupted by user.");
-
-
-/*
- * ImportError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, ImportError,
- "Import can't find module, or can't find name in module.");
-
-
-/*
- * EnvironmentError extends StandardError
- */
-
-/* Where a function has a single filename, such as open() or some
- * of the os module functions, PyErr_SetFromErrnoWithFilename() is
- * called, giving a third argument which is the filename. But, so
- * that old code using in-place unpacking doesn't break, e.g.:
- *
- * except IOError, (errno, strerror):
- *
- * we hack args so that it only contains two items. This also
- * means we need our own __str__() which prints out the filename
- * when it was supplied.
- */
-static int
-EnvironmentError_init(PyEnvironmentErrorObject *self, PyObject *args,
- PyObject *kwds)
-{
- PyObject *myerrno = NULL, *strerror = NULL, *filename = NULL;
- PyObject *subslice = NULL;
-
- if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
- return -1;
-
- if (PyTuple_GET_SIZE(args) <= 1 || PyTuple_GET_SIZE(args) > 3) {
- return 0;
- }
-
- if (!PyArg_UnpackTuple(args, "EnvironmentError", 2, 3,
- &myerrno, &strerror, &filename)) {
- return -1;
- }
- Py_CLEAR(self->myerrno); /* replacing */
- self->myerrno = myerrno;
- Py_INCREF(self->myerrno);
-
- Py_CLEAR(self->strerror); /* replacing */
- self->strerror = strerror;
- Py_INCREF(self->strerror);
-
- /* self->filename will remain Py_None otherwise */
- if (filename != NULL) {
- Py_CLEAR(self->filename); /* replacing */
- self->filename = filename;
- Py_INCREF(self->filename);
-
- subslice = PyTuple_GetSlice(args, 0, 2);
- if (!subslice)
- return -1;
-
- Py_DECREF(self->args); /* replacing args */
- self->args = subslice;
- }
- return 0;
-}
-
-static int
-EnvironmentError_clear(PyEnvironmentErrorObject *self)
-{
- Py_CLEAR(self->myerrno);
- Py_CLEAR(self->strerror);
- Py_CLEAR(self->filename);
- return BaseException_clear((PyBaseExceptionObject *)self);
-}
-
-static void
-EnvironmentError_dealloc(PyEnvironmentErrorObject *self)
-{
- _PyObject_GC_UNTRACK(self);
- EnvironmentError_clear(self);
- self->ob_type->tp_free((PyObject *)self);
-}
-
-static int
-EnvironmentError_traverse(PyEnvironmentErrorObject *self, visitproc visit,
- void *arg)
-{
- Py_VISIT(self->myerrno);
- Py_VISIT(self->strerror);
- Py_VISIT(self->filename);
- return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
-}
-
-static PyObject *
-EnvironmentError_str(PyEnvironmentErrorObject *self)
-{
- PyObject *rtnval = NULL;
-
- if (self->filename) {
- PyObject *fmt;
- PyObject *repr;
- PyObject *tuple;
-
- fmt = PyString_FromString("[Errno %s] %s: %s");
- if (!fmt)
- return NULL;
-
- repr = PyObject_Repr(self->filename);
- if (!repr) {
- Py_DECREF(fmt);
- return NULL;
- }
- tuple = PyTuple_New(3);
- if (!tuple) {
- Py_DECREF(repr);
- Py_DECREF(fmt);
- return NULL;
- }
-
- if (self->myerrno) {
- Py_INCREF(self->myerrno);
- PyTuple_SET_ITEM(tuple, 0, self->myerrno);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 0, Py_None);
- }
- if (self->strerror) {
- Py_INCREF(self->strerror);
- PyTuple_SET_ITEM(tuple, 1, self->strerror);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 1, Py_None);
- }
-
- PyTuple_SET_ITEM(tuple, 2, repr);
-
- rtnval = PyString_Format(fmt, tuple);
-
- Py_DECREF(fmt);
- Py_DECREF(tuple);
- }
- else if (self->myerrno && self->strerror) {
- PyObject *fmt;
- PyObject *tuple;
-
- fmt = PyString_FromString("[Errno %s] %s");
- if (!fmt)
- return NULL;
-
- tuple = PyTuple_New(2);
- if (!tuple) {
- Py_DECREF(fmt);
- return NULL;
- }
-
- if (self->myerrno) {
- Py_INCREF(self->myerrno);
- PyTuple_SET_ITEM(tuple, 0, self->myerrno);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 0, Py_None);
- }
- if (self->strerror) {
- Py_INCREF(self->strerror);
- PyTuple_SET_ITEM(tuple, 1, self->strerror);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 1, Py_None);
- }
-
- rtnval = PyString_Format(fmt, tuple);
-
- Py_DECREF(fmt);
- Py_DECREF(tuple);
- }
- else
- rtnval = BaseException_str((PyBaseExceptionObject *)self);
-
- return rtnval;
-}
-
-static PyMemberDef EnvironmentError_members[] = {
- {"message", T_OBJECT, offsetof(PyEnvironmentErrorObject, message), 0,
- PyDoc_STR("exception message")},
- {"errno", T_OBJECT, offsetof(PyEnvironmentErrorObject, myerrno), 0,
- PyDoc_STR("exception errno")},
- {"strerror", T_OBJECT, offsetof(PyEnvironmentErrorObject, strerror), 0,
- PyDoc_STR("exception strerror")},
- {"filename", T_OBJECT, offsetof(PyEnvironmentErrorObject, filename), 0,
- PyDoc_STR("exception filename")},
- {NULL} /* Sentinel */
-};
-
-
-static PyObject *
-EnvironmentError_reduce(PyEnvironmentErrorObject *self)
-{
- PyObject *args = self->args;
- PyObject *res = NULL, *tmp;
-
- /* self->args is only the first two real arguments if there was a
- * file name given to EnvironmentError. */
- if (PyTuple_GET_SIZE(args) == 2 && self->filename) {
- args = PyTuple_New(3);
- if (!args) return NULL;
-
- tmp = PyTuple_GET_ITEM(self->args, 0);
- Py_INCREF(tmp);
- PyTuple_SET_ITEM(args, 0, tmp);
-
- tmp = PyTuple_GET_ITEM(self->args, 1);
- Py_INCREF(tmp);
- PyTuple_SET_ITEM(args, 1, tmp);
-
- Py_INCREF(self->filename);
- PyTuple_SET_ITEM(args, 2, self->filename);
- } else
- Py_INCREF(args);
-
- if (self->dict)
- res = PyTuple_Pack(3, self->ob_type, args, self->dict);
- else
- res = PyTuple_Pack(2, self->ob_type, args);
- Py_DECREF(args);
- return res;
-}
-
-
-static PyMethodDef EnvironmentError_methods[] = {
- {"__reduce__", (PyCFunction)EnvironmentError_reduce, METH_NOARGS},
- {NULL}
-};
-
-ComplexExtendsException(PyExc_StandardError, EnvironmentError,
- EnvironmentError, EnvironmentError_dealloc,
- EnvironmentError_methods, EnvironmentError_members,
- EnvironmentError_str,
- "Base class for I/O related errors.");
-
-
-/*
- * IOError extends EnvironmentError
- */
-MiddlingExtendsException(PyExc_EnvironmentError, IOError,
- EnvironmentError, "I/O operation failed.");
-
-
-/*
- * OSError extends EnvironmentError
- */
-MiddlingExtendsException(PyExc_EnvironmentError, OSError,
- EnvironmentError, "OS system call failed.");
-
-
-/*
- * WindowsError extends OSError
- */
-#ifdef MS_WINDOWS
-#include "errmap.h"
-
-static int
-WindowsError_clear(PyWindowsErrorObject *self)
-{
- Py_CLEAR(self->myerrno);
- Py_CLEAR(self->strerror);
- Py_CLEAR(self->filename);
- Py_CLEAR(self->winerror);
- return BaseException_clear((PyBaseExceptionObject *)self);
-}
-
-static void
-WindowsError_dealloc(PyWindowsErrorObject *self)
-{
- _PyObject_GC_UNTRACK(self);
- WindowsError_clear(self);
- self->ob_type->tp_free((PyObject *)self);
-}
-
-static int
-WindowsError_traverse(PyWindowsErrorObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->myerrno);
- Py_VISIT(self->strerror);
- Py_VISIT(self->filename);
- Py_VISIT(self->winerror);
- return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
-}
-
-static int
-WindowsError_init(PyWindowsErrorObject *self, PyObject *args, PyObject *kwds)
-{
- PyObject *o_errcode = NULL;
- long errcode;
- long posix_errno;
-
- if (EnvironmentError_init((PyEnvironmentErrorObject *)self, args, kwds)
- == -1)
- return -1;
-
- if (self->myerrno == NULL)
- return 0;
-
- /* Set errno to the POSIX errno, and winerror to the Win32
- error code. */
- errcode = PyInt_AsLong(self->myerrno);
- if (errcode == -1 && PyErr_Occurred())
- return -1;
- posix_errno = winerror_to_errno(errcode);
-
- Py_CLEAR(self->winerror);
- self->winerror = self->myerrno;
-
- o_errcode = PyInt_FromLong(posix_errno);
- if (!o_errcode)
- return -1;
-
- self->myerrno = o_errcode;
-
- return 0;
-}
-
-
-static PyObject *
-WindowsError_str(PyWindowsErrorObject *self)
-{
- PyObject *rtnval = NULL;
-
- if (self->filename) {
- PyObject *fmt;
- PyObject *repr;
- PyObject *tuple;
-
- fmt = PyString_FromString("[Error %s] %s: %s");
- if (!fmt)
- return NULL;
-
- repr = PyObject_Repr(self->filename);
- if (!repr) {
- Py_DECREF(fmt);
- return NULL;
- }
- tuple = PyTuple_New(3);
- if (!tuple) {
- Py_DECREF(repr);
- Py_DECREF(fmt);
- return NULL;
- }
-
- if (self->winerror) {
- Py_INCREF(self->winerror);
- PyTuple_SET_ITEM(tuple, 0, self->winerror);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 0, Py_None);
- }
- if (self->strerror) {
- Py_INCREF(self->strerror);
- PyTuple_SET_ITEM(tuple, 1, self->strerror);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 1, Py_None);
- }
-
- PyTuple_SET_ITEM(tuple, 2, repr);
-
- rtnval = PyString_Format(fmt, tuple);
-
- Py_DECREF(fmt);
- Py_DECREF(tuple);
- }
- else if (self->winerror && self->strerror) {
- PyObject *fmt;
- PyObject *tuple;
-
- fmt = PyString_FromString("[Error %s] %s");
- if (!fmt)
- return NULL;
-
- tuple = PyTuple_New(2);
- if (!tuple) {
- Py_DECREF(fmt);
- return NULL;
- }
-
- if (self->winerror) {
- Py_INCREF(self->winerror);
- PyTuple_SET_ITEM(tuple, 0, self->winerror);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 0, Py_None);
- }
- if (self->strerror) {
- Py_INCREF(self->strerror);
- PyTuple_SET_ITEM(tuple, 1, self->strerror);
- }
- else {
- Py_INCREF(Py_None);
- PyTuple_SET_ITEM(tuple, 1, Py_None);
- }
-
- rtnval = PyString_Format(fmt, tuple);
-
- Py_DECREF(fmt);
- Py_DECREF(tuple);
- }
- else
- rtnval = EnvironmentError_str((PyEnvironmentErrorObject *)self);
-
- return rtnval;
-}
-
-static PyMemberDef WindowsError_members[] = {
- {"message", T_OBJECT, offsetof(PyWindowsErrorObject, message), 0,
- PyDoc_STR("exception message")},
- {"errno", T_OBJECT, offsetof(PyWindowsErrorObject, myerrno), 0,
- PyDoc_STR("POSIX exception code")},
- {"strerror", T_OBJECT, offsetof(PyWindowsErrorObject, strerror), 0,
- PyDoc_STR("exception strerror")},
- {"filename", T_OBJECT, offsetof(PyWindowsErrorObject, filename), 0,
- PyDoc_STR("exception filename")},
- {"winerror", T_OBJECT, offsetof(PyWindowsErrorObject, winerror), 0,
- PyDoc_STR("Win32 exception code")},
- {NULL} /* Sentinel */
-};
-
-ComplexExtendsException(PyExc_OSError, WindowsError, WindowsError,
- WindowsError_dealloc, 0, WindowsError_members,
- WindowsError_str, "MS-Windows OS system call failed.");
-
-#endif /* MS_WINDOWS */
-
-
-/*
- * VMSError extends OSError (I think)
- */
-#ifdef __VMS
-MiddlingExtendsException(PyExc_OSError, VMSError, EnvironmentError,
- "OpenVMS OS system call failed.");
-#endif
-
-
-/*
- * EOFError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, EOFError,
- "Read beyond end of file.");
-
-
-/*
- * RuntimeError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, RuntimeError,
- "Unspecified run-time error.");
-
-
-/*
- * NotImplementedError extends RuntimeError
- */
-SimpleExtendsException(PyExc_RuntimeError, NotImplementedError,
- "Method or function hasn't been implemented yet.");
-
-/*
- * NameError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, NameError,
- "Name not found globally.");
-
-/*
- * UnboundLocalError extends NameError
- */
-SimpleExtendsException(PyExc_NameError, UnboundLocalError,
- "Local name referenced but not bound to a value.");
-
-/*
- * AttributeError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, AttributeError,
- "Attribute not found.");
-
-
-/*
- * SyntaxError extends StandardError
- */
-
-static int
-SyntaxError_init(PySyntaxErrorObject *self, PyObject *args, PyObject *kwds)
-{
- PyObject *info = NULL;
- Py_ssize_t lenargs = PyTuple_GET_SIZE(args);
-
- if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
- return -1;
-
- if (lenargs >= 1) {
- Py_CLEAR(self->msg);
- self->msg = PyTuple_GET_ITEM(args, 0);
- Py_INCREF(self->msg);
- }
- if (lenargs == 2) {
- info = PyTuple_GET_ITEM(args, 1);
- info = PySequence_Tuple(info);
- if (!info) return -1;
-
- if (PyTuple_GET_SIZE(info) != 4) {
- /* not a very good error message, but it's what Python 2.4 gives */
- PyErr_SetString(PyExc_IndexError, "tuple index out of range");
- Py_DECREF(info);
- return -1;
- }
-
- Py_CLEAR(self->filename);
- self->filename = PyTuple_GET_ITEM(info, 0);
- Py_INCREF(self->filename);
-
- Py_CLEAR(self->lineno);
- self->lineno = PyTuple_GET_ITEM(info, 1);
- Py_INCREF(self->lineno);
-
- Py_CLEAR(self->offset);
- self->offset = PyTuple_GET_ITEM(info, 2);
- Py_INCREF(self->offset);
-
- Py_CLEAR(self->text);
- self->text = PyTuple_GET_ITEM(info, 3);
- Py_INCREF(self->text);
-
- Py_DECREF(info);
- }
- return 0;
-}
-
-static int
-SyntaxError_clear(PySyntaxErrorObject *self)
-{
- Py_CLEAR(self->msg);
- Py_CLEAR(self->filename);
- Py_CLEAR(self->lineno);
- Py_CLEAR(self->offset);
- Py_CLEAR(self->text);
- Py_CLEAR(self->print_file_and_line);
- return BaseException_clear((PyBaseExceptionObject *)self);
-}
-
-static void
-SyntaxError_dealloc(PySyntaxErrorObject *self)
-{
- _PyObject_GC_UNTRACK(self);
- SyntaxError_clear(self);
- self->ob_type->tp_free((PyObject *)self);
-}
-
-static int
-SyntaxError_traverse(PySyntaxErrorObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->msg);
- Py_VISIT(self->filename);
- Py_VISIT(self->lineno);
- Py_VISIT(self->offset);
- Py_VISIT(self->text);
- Py_VISIT(self->print_file_and_line);
- return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
-}
-
-/* This is called "my_basename" instead of just "basename" to avoid name
- conflicts with glibc; basename is already prototyped if _GNU_SOURCE is
- defined, and Python does define that. */
-static char *
-my_basename(char *name)
-{
- char *cp = name;
- char *result = name;
-
- if (name == NULL)
- return "???";
- while (*cp != '\0') {
- if (*cp == SEP)
- result = cp + 1;
- ++cp;
- }
- return result;
-}
-
-
-static PyObject *
-SyntaxError_str(PySyntaxErrorObject *self)
-{
- PyObject *str;
- PyObject *result;
- int have_filename = 0;
- int have_lineno = 0;
- char *buffer = NULL;
- Py_ssize_t bufsize;
-
- if (self->msg)
- str = PyObject_Str(self->msg);
- else
- str = PyObject_Str(Py_None);
- if (!str) return NULL;
- /* Don't fiddle with non-string return (shouldn't happen anyway) */
- if (!PyString_Check(str)) return str;
-
- /* XXX -- do all the additional formatting with filename and
- lineno here */
-
- have_filename = (self->filename != NULL) &&
- PyString_Check(self->filename);
- have_lineno = (self->lineno != NULL) && PyInt_Check(self->lineno);
-
- if (!have_filename && !have_lineno)
- return str;
-
- bufsize = PyString_GET_SIZE(str) + 64;
- if (have_filename)
- bufsize += PyString_GET_SIZE(self->filename);
-
- buffer = PyMem_MALLOC(bufsize);
- if (buffer == NULL)
- return str;
-
- if (have_filename && have_lineno)
- PyOS_snprintf(buffer, bufsize, "%s (%s, line %ld)",
- PyString_AS_STRING(str),
- my_basename(PyString_AS_STRING(self->filename)),
- PyInt_AsLong(self->lineno));
- else if (have_filename)
- PyOS_snprintf(buffer, bufsize, "%s (%s)",
- PyString_AS_STRING(str),
- my_basename(PyString_AS_STRING(self->filename)));
- else /* only have_lineno */
- PyOS_snprintf(buffer, bufsize, "%s (line %ld)",
- PyString_AS_STRING(str),
- PyInt_AsLong(self->lineno));
-
- result = PyString_FromString(buffer);
- PyMem_FREE(buffer);
-
- if (result == NULL)
- result = str;
- else
- Py_DECREF(str);
- return result;
-}
-
-static PyMemberDef SyntaxError_members[] = {
- {"message", T_OBJECT, offsetof(PySyntaxErrorObject, message), 0,
- PyDoc_STR("exception message")},
- {"msg", T_OBJECT, offsetof(PySyntaxErrorObject, msg), 0,
- PyDoc_STR("exception msg")},
- {"filename", T_OBJECT, offsetof(PySyntaxErrorObject, filename), 0,
- PyDoc_STR("exception filename")},
- {"lineno", T_OBJECT, offsetof(PySyntaxErrorObject, lineno), 0,
- PyDoc_STR("exception lineno")},
- {"offset", T_OBJECT, offsetof(PySyntaxErrorObject, offset), 0,
- PyDoc_STR("exception offset")},
- {"text", T_OBJECT, offsetof(PySyntaxErrorObject, text), 0,
- PyDoc_STR("exception text")},
- {"print_file_and_line", T_OBJECT,
- offsetof(PySyntaxErrorObject, print_file_and_line), 0,
- PyDoc_STR("exception print_file_and_line")},
- {NULL} /* Sentinel */
-};
-
-ComplexExtendsException(PyExc_StandardError, SyntaxError, SyntaxError,
- SyntaxError_dealloc, 0, SyntaxError_members,
- SyntaxError_str, "Invalid syntax.");
-
-
-/*
- * IndentationError extends SyntaxError
- */
-MiddlingExtendsException(PyExc_SyntaxError, IndentationError, SyntaxError,
- "Improper indentation.");
-
-
-/*
- * TabError extends IndentationError
- */
-MiddlingExtendsException(PyExc_IndentationError, TabError, SyntaxError,
- "Improper mixture of spaces and tabs.");
-
-
-/*
- * LookupError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, LookupError,
- "Base class for lookup errors.");
-
-
-/*
- * IndexError extends LookupError
- */
-SimpleExtendsException(PyExc_LookupError, IndexError,
- "Sequence index out of range.");
-
-
-/*
- * KeyError extends LookupError
- */
-static PyObject *
-KeyError_str(PyBaseExceptionObject *self)
-{
- /* If args is a tuple of exactly one item, apply repr to args[0].
- This is done so that e.g. the exception raised by {}[''] prints
- KeyError: ''
- rather than the confusing
- KeyError
- alone. The downside is that if KeyError is raised with an explanatory
- string, that string will be displayed in quotes. Too bad.
- If args is anything else, use the default BaseException__str__().
- */
- if (PyTuple_GET_SIZE(self->args) == 1) {
- return PyObject_Repr(PyTuple_GET_ITEM(self->args, 0));
- }
- return BaseException_str(self);
-}
-
-ComplexExtendsException(PyExc_LookupError, KeyError, BaseException,
- 0, 0, 0, KeyError_str, "Mapping key not found.");
-
-
-/*
- * ValueError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, ValueError,
- "Inappropriate argument value (of correct type).");
-
-/*
- * UnicodeError extends ValueError
- */
-
-SimpleExtendsException(PyExc_ValueError, UnicodeError,
- "Unicode related error.");
-
-#ifdef Py_USING_UNICODE
-static int
-get_int(PyObject *attr, Py_ssize_t *value, const char *name)
-{
- if (!attr) {
- PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
- return -1;
- }
-
- if (PyInt_Check(attr)) {
- *value = PyInt_AS_LONG(attr);
- } else if (PyLong_Check(attr)) {
- *value = _PyLong_AsSsize_t(attr);
- if (*value == -1 && PyErr_Occurred())
- return -1;
- } else {
- PyErr_Format(PyExc_TypeError, "%.200s attribute must be int", name);
- return -1;
- }
- return 0;
-}
-
-static int
-set_ssize_t(PyObject **attr, Py_ssize_t value)
-{
- PyObject *obj = PyInt_FromSsize_t(value);
- if (!obj)
- return -1;
- Py_CLEAR(*attr);
- *attr = obj;
- return 0;
-}
-
-static PyObject *
-get_string(PyObject *attr, const char *name)
-{
- if (!attr) {
- PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
- return NULL;
- }
-
- if (!PyString_Check(attr)) {
- PyErr_Format(PyExc_TypeError, "%.200s attribute must be str", name);
- return NULL;
- }
- Py_INCREF(attr);
- return attr;
-}
-
-
-static int
-set_string(PyObject **attr, const char *value)
-{
- PyObject *obj = PyString_FromString(value);
- if (!obj)
- return -1;
- Py_CLEAR(*attr);
- *attr = obj;
- return 0;
-}
-
-
-static PyObject *
-get_unicode(PyObject *attr, const char *name)
-{
- if (!attr) {
- PyErr_Format(PyExc_TypeError, "%.200s attribute not set", name);
- return NULL;
- }
-
- if (!PyUnicode_Check(attr)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s attribute must be unicode", name);
- return NULL;
- }
- Py_INCREF(attr);
- return attr;
-}
-
-PyObject *
-PyUnicodeEncodeError_GetEncoding(PyObject *exc)
-{
- return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding");
-}
-
-PyObject *
-PyUnicodeDecodeError_GetEncoding(PyObject *exc)
-{
- return get_string(((PyUnicodeErrorObject *)exc)->encoding, "encoding");
-}
-
-PyObject *
-PyUnicodeEncodeError_GetObject(PyObject *exc)
-{
- return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");
-}
-
-PyObject *
-PyUnicodeDecodeError_GetObject(PyObject *exc)
-{
- return get_string(((PyUnicodeErrorObject *)exc)->object, "object");
-}
-
-PyObject *
-PyUnicodeTranslateError_GetObject(PyObject *exc)
-{
- return get_unicode(((PyUnicodeErrorObject *)exc)->object, "object");
-}
-
-int
-PyUnicodeEncodeError_GetStart(PyObject *exc, Py_ssize_t *start)
-{
- if (!get_int(((PyUnicodeErrorObject *)exc)->start, start, "start")) {
- Py_ssize_t size;
- PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,
- "object");
- if (!obj) return -1;
- size = PyUnicode_GET_SIZE(obj);
- if (*start<0)
- *start = 0; /*XXX check for values <0*/
- if (*start>=size)
- *start = size-1;
- Py_DECREF(obj);
- return 0;
- }
- return -1;
-}
-
-
-int
-PyUnicodeDecodeError_GetStart(PyObject *exc, Py_ssize_t *start)
-{
- if (!get_int(((PyUnicodeErrorObject *)exc)->start, start, "start")) {
- Py_ssize_t size;
- PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object,
- "object");
- if (!obj) return -1;
- size = PyString_GET_SIZE(obj);
- if (*start<0)
- *start = 0;
- if (*start>=size)
- *start = size-1;
- Py_DECREF(obj);
- return 0;
- }
- return -1;
-}
-
-
-int
-PyUnicodeTranslateError_GetStart(PyObject *exc, Py_ssize_t *start)
-{
- return PyUnicodeEncodeError_GetStart(exc, start);
-}
-
-
-int
-PyUnicodeEncodeError_SetStart(PyObject *exc, Py_ssize_t start)
-{
- return set_ssize_t(&((PyUnicodeErrorObject *)exc)->start, start);
-}
-
-
-int
-PyUnicodeDecodeError_SetStart(PyObject *exc, Py_ssize_t start)
-{
- return set_ssize_t(&((PyUnicodeErrorObject *)exc)->start, start);
-}
-
-
-int
-PyUnicodeTranslateError_SetStart(PyObject *exc, Py_ssize_t start)
-{
- return set_ssize_t(&((PyUnicodeErrorObject *)exc)->start, start);
-}
-
-
-int
-PyUnicodeEncodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
-{
- if (!get_int(((PyUnicodeErrorObject *)exc)->end, end, "end")) {
- Py_ssize_t size;
- PyObject *obj = get_unicode(((PyUnicodeErrorObject *)exc)->object,
- "object");
- if (!obj) return -1;
- size = PyUnicode_GET_SIZE(obj);
- if (*end<1)
- *end = 1;
- if (*end>size)
- *end = size;
- Py_DECREF(obj);
- return 0;
- }
- return -1;
-}
-
-
-int
-PyUnicodeDecodeError_GetEnd(PyObject *exc, Py_ssize_t *end)
-{
- if (!get_int(((PyUnicodeErrorObject *)exc)->end, end, "end")) {
- Py_ssize_t size;
- PyObject *obj = get_string(((PyUnicodeErrorObject *)exc)->object,
- "object");
- if (!obj) return -1;
- size = PyString_GET_SIZE(obj);
- if (*end<1)
- *end = 1;
- if (*end>size)
- *end = size;
- Py_DECREF(obj);
- return 0;
- }
- return -1;
-}
-
-
-int
-PyUnicodeTranslateError_GetEnd(PyObject *exc, Py_ssize_t *start)
-{
- return PyUnicodeEncodeError_GetEnd(exc, start);
-}
-
-
-int
-PyUnicodeEncodeError_SetEnd(PyObject *exc, Py_ssize_t end)
-{
- return set_ssize_t(&((PyUnicodeErrorObject *)exc)->end, end);
-}
-
-
-int
-PyUnicodeDecodeError_SetEnd(PyObject *exc, Py_ssize_t end)
-{
- return set_ssize_t(&((PyUnicodeErrorObject *)exc)->end, end);
-}
-
-
-int
-PyUnicodeTranslateError_SetEnd(PyObject *exc, Py_ssize_t end)
-{
- return set_ssize_t(&((PyUnicodeErrorObject *)exc)->end, end);
-}
-
-PyObject *
-PyUnicodeEncodeError_GetReason(PyObject *exc)
-{
- return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");
-}
-
-
-PyObject *
-PyUnicodeDecodeError_GetReason(PyObject *exc)
-{
- return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");
-}
-
-
-PyObject *
-PyUnicodeTranslateError_GetReason(PyObject *exc)
-{
- return get_string(((PyUnicodeErrorObject *)exc)->reason, "reason");
-}
-
-
-int
-PyUnicodeEncodeError_SetReason(PyObject *exc, const char *reason)
-{
- return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);
-}
-
-
-int
-PyUnicodeDecodeError_SetReason(PyObject *exc, const char *reason)
-{
- return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);
-}
-
-
-int
-PyUnicodeTranslateError_SetReason(PyObject *exc, const char *reason)
-{
- return set_string(&((PyUnicodeErrorObject *)exc)->reason, reason);
-}
-
-
-static int
-UnicodeError_init(PyUnicodeErrorObject *self, PyObject *args, PyObject *kwds,
- PyTypeObject *objecttype)
-{
- Py_CLEAR(self->encoding);
- Py_CLEAR(self->object);
- Py_CLEAR(self->start);
- Py_CLEAR(self->end);
- Py_CLEAR(self->reason);
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!O!",
- &PyString_Type, &self->encoding,
- objecttype, &self->object,
- &PyInt_Type, &self->start,
- &PyInt_Type, &self->end,
- &PyString_Type, &self->reason)) {
- self->encoding = self->object = self->start = self->end =
- self->reason = NULL;
- return -1;
- }
-
- Py_INCREF(self->encoding);
- Py_INCREF(self->object);
- Py_INCREF(self->start);
- Py_INCREF(self->end);
- Py_INCREF(self->reason);
-
- return 0;
-}
-
-static int
-UnicodeError_clear(PyUnicodeErrorObject *self)
-{
- Py_CLEAR(self->encoding);
- Py_CLEAR(self->object);
- Py_CLEAR(self->start);
- Py_CLEAR(self->end);
- Py_CLEAR(self->reason);
- return BaseException_clear((PyBaseExceptionObject *)self);
-}
-
-static void
-UnicodeError_dealloc(PyUnicodeErrorObject *self)
-{
- _PyObject_GC_UNTRACK(self);
- UnicodeError_clear(self);
- self->ob_type->tp_free((PyObject *)self);
-}
-
-static int
-UnicodeError_traverse(PyUnicodeErrorObject *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->encoding);
- Py_VISIT(self->object);
- Py_VISIT(self->start);
- Py_VISIT(self->end);
- Py_VISIT(self->reason);
- return BaseException_traverse((PyBaseExceptionObject *)self, visit, arg);
-}
-
-static PyMemberDef UnicodeError_members[] = {
- {"message", T_OBJECT, offsetof(PyUnicodeErrorObject, message), 0,
- PyDoc_STR("exception message")},
- {"encoding", T_OBJECT, offsetof(PyUnicodeErrorObject, encoding), 0,
- PyDoc_STR("exception encoding")},
- {"object", T_OBJECT, offsetof(PyUnicodeErrorObject, object), 0,
- PyDoc_STR("exception object")},
- {"start", T_OBJECT, offsetof(PyUnicodeErrorObject, start), 0,
- PyDoc_STR("exception start")},
- {"end", T_OBJECT, offsetof(PyUnicodeErrorObject, end), 0,
- PyDoc_STR("exception end")},
- {"reason", T_OBJECT, offsetof(PyUnicodeErrorObject, reason), 0,
- PyDoc_STR("exception reason")},
- {NULL} /* Sentinel */
-};
-
-
-/*
- * UnicodeEncodeError extends UnicodeError
- */
-
-static int
-UnicodeEncodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
- return -1;
- return UnicodeError_init((PyUnicodeErrorObject *)self, args,
- kwds, &PyUnicode_Type);
-}
-
-static PyObject *
-UnicodeEncodeError_str(PyObject *self)
-{
- Py_ssize_t start;
- Py_ssize_t end;
-
- if (PyUnicodeEncodeError_GetStart(self, &start))
- return NULL;
-
- if (PyUnicodeEncodeError_GetEnd(self, &end))
- return NULL;
-
- if (end==start+1) {
- int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start];
- char badchar_str[20];
- if (badchar <= 0xff)
- PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar);
- else if (badchar <= 0xffff)
- PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar);
- else
- PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar);
- return PyString_FromFormat(
- "'%.400s' codec can't encode character u'\\%s' in position %zd: %.400s",
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding),
- badchar_str,
- start,
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason)
- );
- }
- return PyString_FromFormat(
- "'%.400s' codec can't encode characters in position %zd-%zd: %.400s",
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding),
- start,
- (end-1),
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason)
- );
-}
-
-static PyTypeObject _PyExc_UnicodeEncodeError = {
- PyObject_HEAD_INIT(NULL)
- 0,
- EXC_MODULE_NAME "UnicodeEncodeError",
- sizeof(PyUnicodeErrorObject), 0,
- (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- (reprfunc)UnicodeEncodeError_str, 0, 0, 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- PyDoc_STR("Unicode encoding error."), (traverseproc)UnicodeError_traverse,
- (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
- 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
- (initproc)UnicodeEncodeError_init, 0, BaseException_new,
-};
-PyObject *PyExc_UnicodeEncodeError = (PyObject *)&_PyExc_UnicodeEncodeError;
-
-PyObject *
-PyUnicodeEncodeError_Create(
- const char *encoding, const Py_UNICODE *object, Py_ssize_t length,
- Py_ssize_t start, Py_ssize_t end, const char *reason)
-{
- return PyObject_CallFunction(PyExc_UnicodeEncodeError, "su#nns",
- encoding, object, length, start, end, reason);
-}
-
-
-/*
- * UnicodeDecodeError extends UnicodeError
- */
-
-static int
-UnicodeDecodeError_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
- return -1;
- return UnicodeError_init((PyUnicodeErrorObject *)self, args,
- kwds, &PyString_Type);
-}
-
-static PyObject *
-UnicodeDecodeError_str(PyObject *self)
-{
- Py_ssize_t start = 0;
- Py_ssize_t end = 0;
-
- if (PyUnicodeDecodeError_GetStart(self, &start))
- return NULL;
-
- if (PyUnicodeDecodeError_GetEnd(self, &end))
- return NULL;
-
- if (end==start+1) {
- /* FromFormat does not support %02x, so format that separately */
- char byte[4];
- PyOS_snprintf(byte, sizeof(byte), "%02x",
- ((int)PyString_AS_STRING(((PyUnicodeErrorObject *)self)->object)[start])&0xff);
- return PyString_FromFormat(
- "'%.400s' codec can't decode byte 0x%s in position %zd: %.400s",
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding),
- byte,
- start,
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason)
- );
- }
- return PyString_FromFormat(
- "'%.400s' codec can't decode bytes in position %zd-%zd: %.400s",
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->encoding),
- start,
- (end-1),
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason)
- );
-}
-
-static PyTypeObject _PyExc_UnicodeDecodeError = {
- PyObject_HEAD_INIT(NULL)
- 0,
- EXC_MODULE_NAME "UnicodeDecodeError",
- sizeof(PyUnicodeErrorObject), 0,
- (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- (reprfunc)UnicodeDecodeError_str, 0, 0, 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- PyDoc_STR("Unicode decoding error."), (traverseproc)UnicodeError_traverse,
- (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
- 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
- (initproc)UnicodeDecodeError_init, 0, BaseException_new,
-};
-PyObject *PyExc_UnicodeDecodeError = (PyObject *)&_PyExc_UnicodeDecodeError;
-
-PyObject *
-PyUnicodeDecodeError_Create(
- const char *encoding, const char *object, Py_ssize_t length,
- Py_ssize_t start, Py_ssize_t end, const char *reason)
-{
- assert(length < INT_MAX);
- assert(start < INT_MAX);
- assert(end < INT_MAX);
- return PyObject_CallFunction(PyExc_UnicodeDecodeError, "ss#nns",
- encoding, object, length, start, end, reason);
-}
-
-
-/*
- * UnicodeTranslateError extends UnicodeError
- */
-
-static int
-UnicodeTranslateError_init(PyUnicodeErrorObject *self, PyObject *args,
- PyObject *kwds)
-{
- if (BaseException_init((PyBaseExceptionObject *)self, args, kwds) == -1)
- return -1;
-
- Py_CLEAR(self->object);
- Py_CLEAR(self->start);
- Py_CLEAR(self->end);
- Py_CLEAR(self->reason);
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!",
- &PyUnicode_Type, &self->object,
- &PyInt_Type, &self->start,
- &PyInt_Type, &self->end,
- &PyString_Type, &self->reason)) {
- self->object = self->start = self->end = self->reason = NULL;
- return -1;
- }
-
- Py_INCREF(self->object);
- Py_INCREF(self->start);
- Py_INCREF(self->end);
- Py_INCREF(self->reason);
-
- return 0;
-}
-
-
-static PyObject *
-UnicodeTranslateError_str(PyObject *self)
-{
- Py_ssize_t start;
- Py_ssize_t end;
-
- if (PyUnicodeTranslateError_GetStart(self, &start))
- return NULL;
-
- if (PyUnicodeTranslateError_GetEnd(self, &end))
- return NULL;
-
- if (end==start+1) {
- int badchar = (int)PyUnicode_AS_UNICODE(((PyUnicodeErrorObject *)self)->object)[start];
- char badchar_str[20];
- if (badchar <= 0xff)
- PyOS_snprintf(badchar_str, sizeof(badchar_str), "x%02x", badchar);
- else if (badchar <= 0xffff)
- PyOS_snprintf(badchar_str, sizeof(badchar_str), "u%04x", badchar);
- else
- PyOS_snprintf(badchar_str, sizeof(badchar_str), "U%08x", badchar);
- return PyString_FromFormat(
- "can't translate character u'\\%s' in position %zd: %.400s",
- badchar_str,
- start,
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason)
- );
- }
- return PyString_FromFormat(
- "can't translate characters in position %zd-%zd: %.400s",
- start,
- (end-1),
- PyString_AS_STRING(((PyUnicodeErrorObject *)self)->reason)
- );
-}
-
-static PyTypeObject _PyExc_UnicodeTranslateError = {
- PyObject_HEAD_INIT(NULL)
- 0,
- EXC_MODULE_NAME "UnicodeTranslateError",
- sizeof(PyUnicodeErrorObject), 0,
- (destructor)UnicodeError_dealloc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- (reprfunc)UnicodeTranslateError_str, 0, 0, 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- PyDoc_STR("Unicode translation error."), (traverseproc)UnicodeError_traverse,
- (inquiry)UnicodeError_clear, 0, 0, 0, 0, 0, UnicodeError_members,
- 0, &_PyExc_UnicodeError, 0, 0, 0, offsetof(PyUnicodeErrorObject, dict),
- (initproc)UnicodeTranslateError_init, 0, BaseException_new,
-};
-PyObject *PyExc_UnicodeTranslateError = (PyObject *)&_PyExc_UnicodeTranslateError;
-
-PyObject *
-PyUnicodeTranslateError_Create(
- const Py_UNICODE *object, Py_ssize_t length,
- Py_ssize_t start, Py_ssize_t end, const char *reason)
-{
- return PyObject_CallFunction(PyExc_UnicodeTranslateError, "u#nns",
- object, length, start, end, reason);
-}
-#endif
-
-
-/*
- * AssertionError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, AssertionError,
- "Assertion failed.");
-
-
-/*
- * ArithmeticError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, ArithmeticError,
- "Base class for arithmetic errors.");
-
-
-/*
- * FloatingPointError extends ArithmeticError
- */
-SimpleExtendsException(PyExc_ArithmeticError, FloatingPointError,
- "Floating point operation failed.");
-
-
-/*
- * OverflowError extends ArithmeticError
- */
-SimpleExtendsException(PyExc_ArithmeticError, OverflowError,
- "Result too large to be represented.");
-
-
-/*
- * ZeroDivisionError extends ArithmeticError
- */
-SimpleExtendsException(PyExc_ArithmeticError, ZeroDivisionError,
- "Second argument to a division or modulo operation was zero.");
-
-
-/*
- * SystemError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, SystemError,
- "Internal error in the Python interpreter.\n"
- "\n"
- "Please report this to the Python maintainer, along with the traceback,\n"
- "the Python version, and the hardware/OS platform and version.");
-
-
-/*
- * ReferenceError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, ReferenceError,
- "Weak ref proxy used after referent went away.");
-
-
-/*
- * MemoryError extends StandardError
- */
-SimpleExtendsException(PyExc_StandardError, MemoryError, "Out of memory.");
-
-
-/* Warning category docstrings */
-
-/*
- * Warning extends Exception
- */
-SimpleExtendsException(PyExc_Exception, Warning,
- "Base class for warning categories.");
-
-
-/*
- * UserWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, UserWarning,
- "Base class for warnings generated by user code.");
-
-
-/*
- * DeprecationWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, DeprecationWarning,
- "Base class for warnings about deprecated features.");
-
-
-/*
- * PendingDeprecationWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, PendingDeprecationWarning,
- "Base class for warnings about features which will be deprecated\n"
- "in the future.");
-
-
-/*
- * SyntaxWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, SyntaxWarning,
- "Base class for warnings about dubious syntax.");
-
-
-/*
- * RuntimeWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, RuntimeWarning,
- "Base class for warnings about dubious runtime behavior.");
-
-
-/*
- * FutureWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, FutureWarning,
- "Base class for warnings about constructs that will change semantically\n"
- "in the future.");
-
-
-/*
- * ImportWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, ImportWarning,
- "Base class for warnings about probable mistakes in module imports");
-
-
-/*
- * UnicodeWarning extends Warning
- */
-SimpleExtendsException(PyExc_Warning, UnicodeWarning,
- "Base class for warnings about Unicode related problems, mostly\n"
- "related to conversion problems.");
-
-
-/* Pre-computed MemoryError instance. Best to create this as early as
- * possible and not wait until a MemoryError is actually raised!
- */
-PyObject *PyExc_MemoryErrorInst=NULL;
-
-/* module global functions */
-static PyMethodDef functions[] = {
- /* Sentinel */
- {NULL, NULL}
-};
-
-#define PRE_INIT(TYPE) if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \
- Py_FatalError("exceptions bootstrapping error.");
-
-#define POST_INIT(TYPE) Py_INCREF(PyExc_ ## TYPE); \
- PyModule_AddObject(m, # TYPE, PyExc_ ## TYPE); \
- if (PyDict_SetItemString(bdict, # TYPE, PyExc_ ## TYPE)) \
- Py_FatalError("Module dictionary insertion problem.");
-
-#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
-/* crt variable checking in VisualStudio .NET 2005 */
-#include <crtdbg.h>
-
-static int prevCrtReportMode;
-static _invalid_parameter_handler prevCrtHandler;
-
-/* Invalid parameter handler. Sets a ValueError exception */
-static void
-InvalidParameterHandler(
- const wchar_t * expression,
- const wchar_t * function,
- const wchar_t * file,
- unsigned int line,
- uintptr_t pReserved)
-{
- /* Do nothing, allow execution to continue. Usually this
- * means that the CRT will set errno to EINVAL
- */
-}
-#endif
-
-
-PyMODINIT_FUNC
-_PyExc_Init(void)
-{
- PyObject *m, *bltinmod, *bdict;
-
- PRE_INIT(BaseException)
- PRE_INIT(Exception)
- PRE_INIT(StandardError)
- PRE_INIT(TypeError)
- PRE_INIT(StopIteration)
- PRE_INIT(GeneratorExit)
- PRE_INIT(SystemExit)
- PRE_INIT(KeyboardInterrupt)
- PRE_INIT(ImportError)
- PRE_INIT(EnvironmentError)
- PRE_INIT(IOError)
- PRE_INIT(OSError)
-#ifdef MS_WINDOWS
- PRE_INIT(WindowsError)
-#endif
-#ifdef __VMS
- PRE_INIT(VMSError)
-#endif
- PRE_INIT(EOFError)
- PRE_INIT(RuntimeError)
- PRE_INIT(NotImplementedError)
- PRE_INIT(NameError)
- PRE_INIT(UnboundLocalError)
- PRE_INIT(AttributeError)
- PRE_INIT(SyntaxError)
- PRE_INIT(IndentationError)
- PRE_INIT(TabError)
- PRE_INIT(LookupError)
- PRE_INIT(IndexError)
- PRE_INIT(KeyError)
- PRE_INIT(ValueError)
- PRE_INIT(UnicodeError)
-#ifdef Py_USING_UNICODE
- PRE_INIT(UnicodeEncodeError)
- PRE_INIT(UnicodeDecodeError)
- PRE_INIT(UnicodeTranslateError)
-#endif
- PRE_INIT(AssertionError)
- PRE_INIT(ArithmeticError)
- PRE_INIT(FloatingPointError)
- PRE_INIT(OverflowError)
- PRE_INIT(ZeroDivisionError)
- PRE_INIT(SystemError)
- PRE_INIT(ReferenceError)
- PRE_INIT(MemoryError)
- PRE_INIT(Warning)
- PRE_INIT(UserWarning)
- PRE_INIT(DeprecationWarning)
- PRE_INIT(PendingDeprecationWarning)
- PRE_INIT(SyntaxWarning)
- PRE_INIT(RuntimeWarning)
- PRE_INIT(FutureWarning)
- PRE_INIT(ImportWarning)
- PRE_INIT(UnicodeWarning)
-
- m = Py_InitModule4("exceptions", functions, exceptions_doc,
- (PyObject *)NULL, PYTHON_API_VERSION);
- if (m == NULL) return;
-
- bltinmod = PyImport_ImportModule("__builtin__");
- if (bltinmod == NULL)
- Py_FatalError("exceptions bootstrapping error.");
- bdict = PyModule_GetDict(bltinmod);
- if (bdict == NULL)
- Py_FatalError("exceptions bootstrapping error.");
-
- POST_INIT(BaseException)
- POST_INIT(Exception)
- POST_INIT(StandardError)
- POST_INIT(TypeError)
- POST_INIT(StopIteration)
- POST_INIT(GeneratorExit)
- POST_INIT(SystemExit)
- POST_INIT(KeyboardInterrupt)
- POST_INIT(ImportError)
- POST_INIT(EnvironmentError)
- POST_INIT(IOError)
- POST_INIT(OSError)
-#ifdef MS_WINDOWS
- POST_INIT(WindowsError)
-#endif
-#ifdef __VMS
- POST_INIT(VMSError)
-#endif
- POST_INIT(EOFError)
- POST_INIT(RuntimeError)
- POST_INIT(NotImplementedError)
- POST_INIT(NameError)
- POST_INIT(UnboundLocalError)
- POST_INIT(AttributeError)
- POST_INIT(SyntaxError)
- POST_INIT(IndentationError)
- POST_INIT(TabError)
- POST_INIT(LookupError)
- POST_INIT(IndexError)
- POST_INIT(KeyError)
- POST_INIT(ValueError)
- POST_INIT(UnicodeError)
-#ifdef Py_USING_UNICODE
- POST_INIT(UnicodeEncodeError)
- POST_INIT(UnicodeDecodeError)
- POST_INIT(UnicodeTranslateError)
-#endif
- POST_INIT(AssertionError)
- POST_INIT(ArithmeticError)
- POST_INIT(FloatingPointError)
- POST_INIT(OverflowError)
- POST_INIT(ZeroDivisionError)
- POST_INIT(SystemError)
- POST_INIT(ReferenceError)
- POST_INIT(MemoryError)
- POST_INIT(Warning)
- POST_INIT(UserWarning)
- POST_INIT(DeprecationWarning)
- POST_INIT(PendingDeprecationWarning)
- POST_INIT(SyntaxWarning)
- POST_INIT(RuntimeWarning)
- POST_INIT(FutureWarning)
- POST_INIT(ImportWarning)
- POST_INIT(UnicodeWarning)
-
- PyExc_MemoryErrorInst = BaseException_new(&_PyExc_MemoryError, NULL, NULL);
- if (!PyExc_MemoryErrorInst)
- Py_FatalError("Cannot pre-allocate MemoryError instance\n");
-
- Py_DECREF(bltinmod);
-
-#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
- /* Set CRT argument error handler */
- prevCrtHandler = _set_invalid_parameter_handler(InvalidParameterHandler);
- /* turn off assertions in debug mode */
- prevCrtReportMode = _CrtSetReportMode(_CRT_ASSERT, 0);
-#endif
-}
-
-void
-_PyExc_Fini(void)
-{
- Py_XDECREF(PyExc_MemoryErrorInst);
- PyExc_MemoryErrorInst = NULL;
-#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__)
- /* reset CRT error handling */
- _set_invalid_parameter_handler(prevCrtHandler);
- _CrtSetReportMode(_CRT_ASSERT, prevCrtReportMode);
-#endif
-}
diff --git a/sys/src/cmd/python/Objects/fileobject.c b/sys/src/cmd/python/Objects/fileobject.c
deleted file mode 100644
index 124767ccd..000000000
--- a/sys/src/cmd/python/Objects/fileobject.c
+++ /dev/null
@@ -1,2487 +0,0 @@
-/* File object implementation */
-
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
-#include "structmember.h"
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif /* HAVE_SYS_TYPES_H */
-
-#ifdef MS_WINDOWS
-#define fileno _fileno
-/* can simulate truncate with Win32 API functions; see file_truncate */
-#define HAVE_FTRUNCATE
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-#ifdef _MSC_VER
-/* Need GetVersion to see if on NT so safe to use _wfopen */
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif /* _MSC_VER */
-
-#if defined(PYOS_OS2) && defined(PYCC_GCC)
-#include <io.h>
-#endif
-
-#define BUF(v) PyString_AS_STRING((PyStringObject *)v)
-
-#ifndef DONT_HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#ifdef HAVE_GETC_UNLOCKED
-#define GETC(f) getc_unlocked(f)
-#define FLOCKFILE(f) flockfile(f)
-#define FUNLOCKFILE(f) funlockfile(f)
-#else
-#define GETC(f) getc(f)
-#define FLOCKFILE(f)
-#define FUNLOCKFILE(f)
-#endif
-
-/* Bits in f_newlinetypes */
-#define NEWLINE_UNKNOWN 0 /* No newline seen, yet */
-#define NEWLINE_CR 1 /* \r newline seen */
-#define NEWLINE_LF 2 /* \n newline seen */
-#define NEWLINE_CRLF 4 /* \r\n newline seen */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-FILE *
-PyFile_AsFile(PyObject *f)
-{
- if (f == NULL || !PyFile_Check(f))
- return NULL;
- else
- return ((PyFileObject *)f)->f_fp;
-}
-
-PyObject *
-PyFile_Name(PyObject *f)
-{
- if (f == NULL || !PyFile_Check(f))
- return NULL;
- else
- return ((PyFileObject *)f)->f_name;
-}
-
-/* On Unix, fopen will succeed for directories.
- In Python, there should be no file objects referring to
- directories, so we need a check. */
-
-static PyFileObject*
-dircheck(PyFileObject* f)
-{
-#if defined(HAVE_FSTAT) && defined(S_IFDIR) && defined(EISDIR)
- struct stat buf;
- if (f->f_fp == NULL)
- return f;
- if (fstat(fileno(f->f_fp), &buf) == 0 &&
- S_ISDIR(buf.st_mode)) {
-#ifdef HAVE_STRERROR
- char *msg = strerror(EISDIR);
-#else
- char *msg = "Is a directory";
-#endif
- PyObject *exc = PyObject_CallFunction(PyExc_IOError, "(is)",
- EISDIR, msg);
- PyErr_SetObject(PyExc_IOError, exc);
- Py_XDECREF(exc);
- return NULL;
- }
-#endif
- return f;
-}
-
-
-static PyObject *
-fill_file_fields(PyFileObject *f, FILE *fp, PyObject *name, char *mode,
- int (*close)(FILE *))
-{
- assert(name != NULL);
- assert(f != NULL);
- assert(PyFile_Check(f));
- assert(f->f_fp == NULL);
-
- Py_DECREF(f->f_name);
- Py_DECREF(f->f_mode);
- Py_DECREF(f->f_encoding);
-
- Py_INCREF(name);
- f->f_name = name;
-
- f->f_mode = PyString_FromString(mode);
-
- f->f_close = close;
- f->f_softspace = 0;
- f->f_binary = strchr(mode,'b') != NULL;
- f->f_buf = NULL;
- f->f_univ_newline = (strchr(mode, 'U') != NULL);
- f->f_newlinetypes = NEWLINE_UNKNOWN;
- f->f_skipnextlf = 0;
- Py_INCREF(Py_None);
- f->f_encoding = Py_None;
-
- if (f->f_mode == NULL)
- return NULL;
- f->f_fp = fp;
- f = dircheck(f);
- return (PyObject *) f;
-}
-
-/* check for known incorrect mode strings - problem is, platforms are
- free to accept any mode characters they like and are supposed to
- ignore stuff they don't understand... write or append mode with
- universal newline support is expressly forbidden by PEP 278.
- Additionally, remove the 'U' from the mode string as platforms
- won't know what it is. */
-/* zero return is kewl - one is un-kewl */
-static int
-sanitize_the_mode(char *mode)
-{
- char *upos;
- size_t len = strlen(mode);
-
- if (!len) {
- PyErr_SetString(PyExc_ValueError, "empty mode string");
- return 1;
- }
-
- upos = strchr(mode, 'U');
- if (upos) {
- memmove(upos, upos+1, len-(upos-mode)); /* incl null char */
-
- if (mode[0] == 'w' || mode[0] == 'a') {
- PyErr_Format(PyExc_ValueError, "universal newline "
- "mode can only be used with modes "
- "starting with 'r'");
- return 1;
- }
-
- if (mode[0] != 'r') {
- memmove(mode+1, mode, strlen(mode)+1);
- mode[0] = 'r';
- }
-
- if (!strchr(mode, 'b')) {
- memmove(mode+2, mode+1, strlen(mode));
- mode[1] = 'b';
- }
- } else if (mode[0] != 'r' && mode[0] != 'w' && mode[0] != 'a') {
- PyErr_Format(PyExc_ValueError, "mode string must begin with "
- "one of 'r', 'w', 'a' or 'U', not '%.200s'", mode);
- return 1;
- }
-
- return 0;
-}
-
-static PyObject *
-open_the_file(PyFileObject *f, char *name, char *mode)
-{
- char *newmode;
- assert(f != NULL);
- assert(PyFile_Check(f));
-#ifdef MS_WINDOWS
- /* windows ignores the passed name in order to support Unicode */
- assert(f->f_name != NULL);
-#else
- assert(name != NULL);
-#endif
- assert(mode != NULL);
- assert(f->f_fp == NULL);
-
- /* probably need to replace 'U' by 'rb' */
- newmode = PyMem_MALLOC(strlen(mode) + 3);
- if (!newmode) {
- PyErr_NoMemory();
- return NULL;
- }
- strcpy(newmode, mode);
-
- if (sanitize_the_mode(newmode)) {
- f = NULL;
- goto cleanup;
- }
-
- /* rexec.py can't stop a user from getting the file() constructor --
- all they have to do is get *any* file object f, and then do
- type(f). Here we prevent them from doing damage with it. */
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_IOError,
- "file() constructor not accessible in restricted mode");
- f = NULL;
- goto cleanup;
- }
- errno = 0;
-
-#ifdef MS_WINDOWS
- if (PyUnicode_Check(f->f_name)) {
- PyObject *wmode;
- wmode = PyUnicode_DecodeASCII(newmode, strlen(newmode), NULL);
- if (f->f_name && wmode) {
- Py_BEGIN_ALLOW_THREADS
- /* PyUnicode_AS_UNICODE OK without thread
- lock as it is a simple dereference. */
- f->f_fp = _wfopen(PyUnicode_AS_UNICODE(f->f_name),
- PyUnicode_AS_UNICODE(wmode));
- Py_END_ALLOW_THREADS
- }
- Py_XDECREF(wmode);
- }
-#endif
- if (NULL == f->f_fp && NULL != name) {
- Py_BEGIN_ALLOW_THREADS
- f->f_fp = fopen(name, newmode);
- Py_END_ALLOW_THREADS
- }
-
- if (f->f_fp == NULL) {
-#if defined _MSC_VER && (_MSC_VER < 1400 || !defined(__STDC_SECURE_LIB__))
- /* MSVC 6 (Microsoft) leaves errno at 0 for bad mode strings,
- * across all Windows flavors. When it sets EINVAL varies
- * across Windows flavors, the exact conditions aren't
- * documented, and the answer lies in the OS's implementation
- * of Win32's CreateFile function (whose source is secret).
- * Seems the best we can do is map EINVAL to ENOENT.
- * Starting with Visual Studio .NET 2005, EINVAL is correctly
- * set by our CRT error handler (set in exceptions.c.)
- */
- if (errno == 0) /* bad mode string */
- errno = EINVAL;
- else if (errno == EINVAL) /* unknown, but not a mode string */
- errno = ENOENT;
-#endif
- if (errno == EINVAL)
- PyErr_Format(PyExc_IOError, "invalid mode: %s",
- mode);
- else
- PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, f->f_name);
- f = NULL;
- }
- if (f != NULL)
- f = dircheck(f);
-
-cleanup:
- PyMem_FREE(newmode);
-
- return (PyObject *)f;
-}
-
-PyObject *
-PyFile_FromFile(FILE *fp, char *name, char *mode, int (*close)(FILE *))
-{
- PyFileObject *f = (PyFileObject *)PyFile_Type.tp_new(&PyFile_Type,
- NULL, NULL);
- if (f != NULL) {
- PyObject *o_name = PyString_FromString(name);
- if (o_name == NULL)
- return NULL;
- if (fill_file_fields(f, fp, o_name, mode, close) == NULL) {
- Py_DECREF(f);
- f = NULL;
- }
- Py_DECREF(o_name);
- }
- return (PyObject *) f;
-}
-
-PyObject *
-PyFile_FromString(char *name, char *mode)
-{
- extern int fclose(FILE *);
- PyFileObject *f;
-
- f = (PyFileObject *)PyFile_FromFile((FILE *)NULL, name, mode, fclose);
- if (f != NULL) {
- if (open_the_file(f, name, mode) == NULL) {
- Py_DECREF(f);
- f = NULL;
- }
- }
- return (PyObject *)f;
-}
-
-void
-PyFile_SetBufSize(PyObject *f, int bufsize)
-{
- PyFileObject *file = (PyFileObject *)f;
- if (bufsize >= 0) {
- int type;
- switch (bufsize) {
- case 0:
- type = _IONBF;
- break;
-#ifdef HAVE_SETVBUF
- case 1:
- type = _IOLBF;
- bufsize = BUFSIZ;
- break;
-#endif
- default:
- type = _IOFBF;
-#ifndef HAVE_SETVBUF
- bufsize = BUFSIZ;
-#endif
- break;
- }
- fflush(file->f_fp);
- if (type == _IONBF) {
- PyMem_Free(file->f_setbuf);
- file->f_setbuf = NULL;
- } else {
- file->f_setbuf = (char *)PyMem_Realloc(file->f_setbuf,
- bufsize);
- }
-#ifdef HAVE_SETVBUF
- setvbuf(file->f_fp, file->f_setbuf, type, bufsize);
-#else /* !HAVE_SETVBUF */
- setbuf(file->f_fp, file->f_setbuf);
-#endif /* !HAVE_SETVBUF */
- }
-}
-
-/* Set the encoding used to output Unicode strings.
- Returh 1 on success, 0 on failure. */
-
-int
-PyFile_SetEncoding(PyObject *f, const char *enc)
-{
- PyFileObject *file = (PyFileObject*)f;
- PyObject *str = PyString_FromString(enc);
-
- assert(PyFile_Check(f));
- if (!str)
- return 0;
- Py_DECREF(file->f_encoding);
- file->f_encoding = str;
- return 1;
-}
-
-static PyObject *
-err_closed(void)
-{
- PyErr_SetString(PyExc_ValueError, "I/O operation on closed file");
- return NULL;
-}
-
-/* Refuse regular file I/O if there's data in the iteration-buffer.
- * Mixing them would cause data to arrive out of order, as the read*
- * methods don't use the iteration buffer. */
-static PyObject *
-err_iterbuffered(void)
-{
- PyErr_SetString(PyExc_ValueError,
- "Mixing iteration and read methods would lose data");
- return NULL;
-}
-
-static void drop_readahead(PyFileObject *);
-
-/* Methods */
-
-static void
-file_dealloc(PyFileObject *f)
-{
- int sts = 0;
- if (f->weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) f);
- if (f->f_fp != NULL && f->f_close != NULL) {
- Py_BEGIN_ALLOW_THREADS
- sts = (*f->f_close)(f->f_fp);
- Py_END_ALLOW_THREADS
- if (sts == EOF)
-#ifdef HAVE_STRERROR
- PySys_WriteStderr("close failed: [Errno %d] %s\n", errno, strerror(errno));
-#else
- PySys_WriteStderr("close failed: [Errno %d]\n", errno);
-#endif
- }
- PyMem_Free(f->f_setbuf);
- Py_XDECREF(f->f_name);
- Py_XDECREF(f->f_mode);
- Py_XDECREF(f->f_encoding);
- drop_readahead(f);
- f->ob_type->tp_free((PyObject *)f);
-}
-
-static PyObject *
-file_repr(PyFileObject *f)
-{
- if (PyUnicode_Check(f->f_name)) {
-#ifdef Py_USING_UNICODE
- PyObject *ret = NULL;
- PyObject *name = PyUnicode_AsUnicodeEscapeString(f->f_name);
- const char *name_str = name ? PyString_AsString(name) : "?";
- ret = PyString_FromFormat("<%s file u'%s', mode '%s' at %p>",
- f->f_fp == NULL ? "closed" : "open",
- name_str,
- PyString_AsString(f->f_mode),
- f);
- Py_XDECREF(name);
- return ret;
-#endif
- } else {
- return PyString_FromFormat("<%s file '%s', mode '%s' at %p>",
- f->f_fp == NULL ? "closed" : "open",
- PyString_AsString(f->f_name),
- PyString_AsString(f->f_mode),
- f);
- }
-}
-
-static PyObject *
-file_close(PyFileObject *f)
-{
- int sts = 0;
- if (f->f_fp != NULL) {
- if (f->f_close != NULL) {
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- sts = (*f->f_close)(f->f_fp);
- Py_END_ALLOW_THREADS
- }
- f->f_fp = NULL;
- }
- PyMem_Free(f->f_setbuf);
- f->f_setbuf = NULL;
- if (sts == EOF)
- return PyErr_SetFromErrno(PyExc_IOError);
- if (sts != 0)
- return PyInt_FromLong((long)sts);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-
-/* Our very own off_t-like type, 64-bit if possible */
-#if !defined(HAVE_LARGEFILE_SUPPORT)
-typedef off_t Py_off_t;
-#elif SIZEOF_OFF_T >= 8
-typedef off_t Py_off_t;
-#elif SIZEOF_FPOS_T >= 8
-typedef fpos_t Py_off_t;
-#else
-#error "Large file support, but neither off_t nor fpos_t is large enough."
-#endif
-
-
-/* a portable fseek() function
- return 0 on success, non-zero on failure (with errno set) */
-static int
-_portable_fseek(FILE *fp, Py_off_t offset, int whence)
-{
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- return fseek(fp, offset, whence);
-#elif defined(HAVE_FSEEKO) && SIZEOF_OFF_T >= 8
- return fseeko(fp, offset, whence);
-#elif defined(HAVE_FSEEK64)
- return fseek64(fp, offset, whence);
-#elif defined(__BEOS__)
- return _fseek(fp, offset, whence);
-#elif SIZEOF_FPOS_T >= 8
- /* lacking a 64-bit capable fseek(), use a 64-bit capable fsetpos()
- and fgetpos() to implement fseek()*/
- fpos_t pos;
- switch (whence) {
- case SEEK_END:
-#ifdef MS_WINDOWS
- fflush(fp);
- if (_lseeki64(fileno(fp), 0, 2) == -1)
- return -1;
-#else
- if (fseek(fp, 0, SEEK_END) != 0)
- return -1;
-#endif
- /* fall through */
- case SEEK_CUR:
- if (fgetpos(fp, &pos) != 0)
- return -1;
- offset += pos;
- break;
- /* case SEEK_SET: break; */
- }
- return fsetpos(fp, &offset);
-#else
-#error "Large file support, but no way to fseek."
-#endif
-}
-
-
-/* a portable ftell() function
- Return -1 on failure with errno set appropriately, current file
- position on success */
-static Py_off_t
-_portable_ftell(FILE* fp)
-{
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- return ftell(fp);
-#elif defined(HAVE_FTELLO) && SIZEOF_OFF_T >= 8
- return ftello(fp);
-#elif defined(HAVE_FTELL64)
- return ftell64(fp);
-#elif SIZEOF_FPOS_T >= 8
- fpos_t pos;
- if (fgetpos(fp, &pos) != 0)
- return -1;
- return pos;
-#else
-#error "Large file support, but no way to ftell."
-#endif
-}
-
-
-static PyObject *
-file_seek(PyFileObject *f, PyObject *args)
-{
- int whence;
- int ret;
- Py_off_t offset;
- PyObject *offobj;
-
- if (f->f_fp == NULL)
- return err_closed();
- drop_readahead(f);
- whence = 0;
- if (!PyArg_ParseTuple(args, "O|i:seek", &offobj, &whence))
- return NULL;
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- offset = PyInt_AsLong(offobj);
-#else
- if(PyLong_Check(offobj))
- offset = PyLong_AsLongLong(offobj);
- else
- offset = PyInt_AsLong(offobj);
-#endif
- if (PyErr_Occurred())
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- ret = _portable_fseek(f->f_fp, offset, whence);
- Py_END_ALLOW_THREADS
-
- if (ret != 0) {
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- return NULL;
- }
- f->f_skipnextlf = 0;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-
-#ifdef HAVE_FTRUNCATE
-static PyObject *
-file_truncate(PyFileObject *f, PyObject *args)
-{
- Py_off_t newsize;
- PyObject *newsizeobj = NULL;
- Py_off_t initialpos;
- int ret;
-
- if (f->f_fp == NULL)
- return err_closed();
- if (!PyArg_UnpackTuple(args, "truncate", 0, 1, &newsizeobj))
- return NULL;
-
- /* Get current file position. If the file happens to be open for
- * update and the last operation was an input operation, C doesn't
- * define what the later fflush() will do, but we promise truncate()
- * won't change the current position (and fflush() *does* change it
- * then at least on Windows). The easiest thing is to capture
- * current pos now and seek back to it at the end.
- */
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- initialpos = _portable_ftell(f->f_fp);
- Py_END_ALLOW_THREADS
- if (initialpos == -1)
- goto onioerror;
-
- /* Set newsize to current postion if newsizeobj NULL, else to the
- * specified value.
- */
- if (newsizeobj != NULL) {
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- newsize = PyInt_AsLong(newsizeobj);
-#else
- if(PyLong_Check(newsizeobj))
- newsize = PyLong_AsLongLong(newsizeobj);
- else
- newsize = PyInt_AsLong(newsizeobj);
-#endif
- if (PyErr_Occurred())
- return NULL;
- }
- else /* default to current position */
- newsize = initialpos;
-
- /* Flush the stream. We're mixing stream-level I/O with lower-level
- * I/O, and a flush may be necessary to synch both platform views
- * of the current file state.
- */
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- ret = fflush(f->f_fp);
- Py_END_ALLOW_THREADS
- if (ret != 0)
- goto onioerror;
-
-#ifdef MS_WINDOWS
- /* MS _chsize doesn't work if newsize doesn't fit in 32 bits,
- so don't even try using it. */
- {
- HANDLE hFile;
-
- /* Have to move current pos to desired endpoint on Windows. */
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- ret = _portable_fseek(f->f_fp, newsize, SEEK_SET) != 0;
- Py_END_ALLOW_THREADS
- if (ret)
- goto onioerror;
-
- /* Truncate. Note that this may grow the file! */
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- hFile = (HANDLE)_get_osfhandle(fileno(f->f_fp));
- ret = hFile == (HANDLE)-1;
- if (ret == 0) {
- ret = SetEndOfFile(hFile) == 0;
- if (ret)
- errno = EACCES;
- }
- Py_END_ALLOW_THREADS
- if (ret)
- goto onioerror;
- }
-#else
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- ret = ftruncate(fileno(f->f_fp), newsize);
- Py_END_ALLOW_THREADS
- if (ret != 0)
- goto onioerror;
-#endif /* !MS_WINDOWS */
-
- /* Restore original file position. */
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- ret = _portable_fseek(f->f_fp, initialpos, SEEK_SET) != 0;
- Py_END_ALLOW_THREADS
- if (ret)
- goto onioerror;
-
- Py_INCREF(Py_None);
- return Py_None;
-
-onioerror:
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- return NULL;
-}
-#endif /* HAVE_FTRUNCATE */
-
-static PyObject *
-file_tell(PyFileObject *f)
-{
- Py_off_t pos;
-
- if (f->f_fp == NULL)
- return err_closed();
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- pos = _portable_ftell(f->f_fp);
- Py_END_ALLOW_THREADS
- if (pos == -1) {
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- return NULL;
- }
- if (f->f_skipnextlf) {
- int c;
- c = GETC(f->f_fp);
- if (c == '\n') {
- pos++;
- f->f_skipnextlf = 0;
- } else if (c != EOF) ungetc(c, f->f_fp);
- }
-#if !defined(HAVE_LARGEFILE_SUPPORT)
- return PyInt_FromLong(pos);
-#else
- return PyLong_FromLongLong(pos);
-#endif
-}
-
-static PyObject *
-file_fileno(PyFileObject *f)
-{
- if (f->f_fp == NULL)
- return err_closed();
- return PyInt_FromLong((long) fileno(f->f_fp));
-}
-
-static PyObject *
-file_flush(PyFileObject *f)
-{
- int res;
-
- if (f->f_fp == NULL)
- return err_closed();
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- res = fflush(f->f_fp);
- Py_END_ALLOW_THREADS
- if (res != 0) {
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- return NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-file_isatty(PyFileObject *f)
-{
- long res;
- if (f->f_fp == NULL)
- return err_closed();
- Py_BEGIN_ALLOW_THREADS
- res = isatty((int)fileno(f->f_fp));
- Py_END_ALLOW_THREADS
- return PyBool_FromLong(res);
-}
-
-
-#if BUFSIZ < 8192
-#define SMALLCHUNK 8192
-#else
-#define SMALLCHUNK BUFSIZ
-#endif
-
-#if SIZEOF_INT < 4
-#define BIGCHUNK (512 * 32)
-#else
-#define BIGCHUNK (512 * 1024)
-#endif
-
-static size_t
-new_buffersize(PyFileObject *f, size_t currentsize)
-{
-#ifdef HAVE_FSTAT
- off_t pos, end;
- struct stat st;
- if (fstat(fileno(f->f_fp), &st) == 0) {
- end = st.st_size;
- /* The following is not a bug: we really need to call lseek()
- *and* ftell(). The reason is that some stdio libraries
- mistakenly flush their buffer when ftell() is called and
- the lseek() call it makes fails, thereby throwing away
- data that cannot be recovered in any way. To avoid this,
- we first test lseek(), and only call ftell() if lseek()
- works. We can't use the lseek() value either, because we
- need to take the amount of buffered data into account.
- (Yet another reason why stdio stinks. :-) */
- pos = lseek(fileno(f->f_fp), 0L, SEEK_CUR);
- if (pos >= 0) {
- pos = ftell(f->f_fp);
- }
- if (pos < 0)
- clearerr(f->f_fp);
- if (end > pos && pos >= 0)
- return currentsize + end - pos + 1;
- /* Add 1 so if the file were to grow we'd notice. */
- }
-#endif
- if (currentsize > SMALLCHUNK) {
- /* Keep doubling until we reach BIGCHUNK;
- then keep adding BIGCHUNK. */
- if (currentsize <= BIGCHUNK)
- return currentsize + currentsize;
- else
- return currentsize + BIGCHUNK;
- }
- return currentsize + SMALLCHUNK;
-}
-
-#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
-#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK || (x) == EAGAIN)
-#else
-#ifdef EWOULDBLOCK
-#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK)
-#else
-#ifdef EAGAIN
-#define BLOCKED_ERRNO(x) ((x) == EAGAIN)
-#else
-#define BLOCKED_ERRNO(x) 0
-#endif
-#endif
-#endif
-
-static PyObject *
-file_read(PyFileObject *f, PyObject *args)
-{
- long bytesrequested = -1;
- size_t bytesread, buffersize, chunksize;
- PyObject *v;
-
- if (f->f_fp == NULL)
- return err_closed();
- /* refuse to mix with f.next() */
- if (f->f_buf != NULL &&
- (f->f_bufend - f->f_bufptr) > 0 &&
- f->f_buf[0] != '\0')
- return err_iterbuffered();
- if (!PyArg_ParseTuple(args, "|l:read", &bytesrequested))
- return NULL;
- if (bytesrequested < 0)
- buffersize = new_buffersize(f, (size_t)0);
- else
- buffersize = bytesrequested;
- if (buffersize > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "requested number of bytes is more than a Python string can hold");
- return NULL;
- }
- v = PyString_FromStringAndSize((char *)NULL, buffersize);
- if (v == NULL)
- return NULL;
- bytesread = 0;
- for (;;) {
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- chunksize = Py_UniversalNewlineFread(BUF(v) + bytesread,
- buffersize - bytesread, f->f_fp, (PyObject *)f);
- Py_END_ALLOW_THREADS
- if (chunksize == 0) {
- if (!ferror(f->f_fp))
- break;
- clearerr(f->f_fp);
- /* When in non-blocking mode, data shouldn't
- * be discarded if a blocking signal was
- * received. That will also happen if
- * chunksize != 0, but bytesread < buffersize. */
- if (bytesread > 0 && BLOCKED_ERRNO(errno))
- break;
- PyErr_SetFromErrno(PyExc_IOError);
- Py_DECREF(v);
- return NULL;
- }
- bytesread += chunksize;
- if (bytesread < buffersize) {
- clearerr(f->f_fp);
- break;
- }
- if (bytesrequested < 0) {
- buffersize = new_buffersize(f, buffersize);
- if (_PyString_Resize(&v, buffersize) < 0)
- return NULL;
- } else {
- /* Got what was requested. */
- break;
- }
- }
- if (bytesread != buffersize)
- _PyString_Resize(&v, bytesread);
- return v;
-}
-
-static PyObject *
-file_readinto(PyFileObject *f, PyObject *args)
-{
- char *ptr;
- Py_ssize_t ntodo;
- Py_ssize_t ndone, nnow;
-
- if (f->f_fp == NULL)
- return err_closed();
- /* refuse to mix with f.next() */
- if (f->f_buf != NULL &&
- (f->f_bufend - f->f_bufptr) > 0 &&
- f->f_buf[0] != '\0')
- return err_iterbuffered();
- if (!PyArg_ParseTuple(args, "w#", &ptr, &ntodo))
- return NULL;
- ndone = 0;
- while (ntodo > 0) {
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp,
- (PyObject *)f);
- Py_END_ALLOW_THREADS
- if (nnow == 0) {
- if (!ferror(f->f_fp))
- break;
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- return NULL;
- }
- ndone += nnow;
- ntodo -= nnow;
- }
- return PyInt_FromSsize_t(ndone);
-}
-
-/**************************************************************************
-Routine to get next line using platform fgets().
-
-Under MSVC 6:
-
-+ MS threadsafe getc is very slow (multiple layers of function calls before+
- after each character, to lock+unlock the stream).
-+ The stream-locking functions are MS-internal -- can't access them from user
- code.
-+ There's nothing Tim could find in the MS C or platform SDK libraries that
- can worm around this.
-+ MS fgets locks/unlocks only once per line; it's the only hook we have.
-
-So we use fgets for speed(!), despite that it's painful.
-
-MS realloc is also slow.
-
-Reports from other platforms on this method vs getc_unlocked (which MS doesn't
-have):
- Linux a wash
- Solaris a wash
- Tru64 Unix getline_via_fgets significantly faster
-
-CAUTION: The C std isn't clear about this: in those cases where fgets
-writes something into the buffer, can it write into any position beyond the
-required trailing null byte? MSVC 6 fgets does not, and no platform is (yet)
-known on which it does; and it would be a strange way to code fgets. Still,
-getline_via_fgets may not work correctly if it does. The std test
-test_bufio.py should fail if platform fgets() routinely writes beyond the
-trailing null byte. #define DONT_USE_FGETS_IN_GETLINE to disable this code.
-**************************************************************************/
-
-/* Use this routine if told to, or by default on non-get_unlocked()
- * platforms unless told not to. Yikes! Let's spell that out:
- * On a platform with getc_unlocked():
- * By default, use getc_unlocked().
- * If you want to use fgets() instead, #define USE_FGETS_IN_GETLINE.
- * On a platform without getc_unlocked():
- * By default, use fgets().
- * If you don't want to use fgets(), #define DONT_USE_FGETS_IN_GETLINE.
- */
-#if !defined(USE_FGETS_IN_GETLINE) && !defined(HAVE_GETC_UNLOCKED)
-#define USE_FGETS_IN_GETLINE
-#endif
-
-#if defined(DONT_USE_FGETS_IN_GETLINE) && defined(USE_FGETS_IN_GETLINE)
-#undef USE_FGETS_IN_GETLINE
-#endif
-
-#ifdef USE_FGETS_IN_GETLINE
-static PyObject*
-getline_via_fgets(FILE *fp)
-{
-/* INITBUFSIZE is the maximum line length that lets us get away with the fast
- * no-realloc, one-fgets()-call path. Boosting it isn't free, because we have
- * to fill this much of the buffer with a known value in order to figure out
- * how much of the buffer fgets() overwrites. So if INITBUFSIZE is larger
- * than "most" lines, we waste time filling unused buffer slots. 100 is
- * surely adequate for most peoples' email archives, chewing over source code,
- * etc -- "regular old text files".
- * MAXBUFSIZE is the maximum line length that lets us get away with the less
- * fast (but still zippy) no-realloc, two-fgets()-call path. See above for
- * cautions about boosting that. 300 was chosen because the worst real-life
- * text-crunching job reported on Python-Dev was a mail-log crawler where over
- * half the lines were 254 chars.
- */
-#define INITBUFSIZE 100
-#define MAXBUFSIZE 300
- char* p; /* temp */
- char buf[MAXBUFSIZE];
- PyObject* v; /* the string object result */
- char* pvfree; /* address of next free slot */
- char* pvend; /* address one beyond last free slot */
- size_t nfree; /* # of free buffer slots; pvend-pvfree */
- size_t total_v_size; /* total # of slots in buffer */
- size_t increment; /* amount to increment the buffer */
- size_t prev_v_size;
-
- /* Optimize for normal case: avoid _PyString_Resize if at all
- * possible via first reading into stack buffer "buf".
- */
- total_v_size = INITBUFSIZE; /* start small and pray */
- pvfree = buf;
- for (;;) {
- Py_BEGIN_ALLOW_THREADS
- pvend = buf + total_v_size;
- nfree = pvend - pvfree;
- memset(pvfree, '\n', nfree);
- assert(nfree < INT_MAX); /* Should be atmost MAXBUFSIZE */
- p = fgets(pvfree, (int)nfree, fp);
- Py_END_ALLOW_THREADS
-
- if (p == NULL) {
- clearerr(fp);
- if (PyErr_CheckSignals())
- return NULL;
- v = PyString_FromStringAndSize(buf, pvfree - buf);
- return v;
- }
- /* fgets read *something* */
- p = memchr(pvfree, '\n', nfree);
- if (p != NULL) {
- /* Did the \n come from fgets or from us?
- * Since fgets stops at the first \n, and then writes
- * \0, if it's from fgets a \0 must be next. But if
- * that's so, it could not have come from us, since
- * the \n's we filled the buffer with have only more
- * \n's to the right.
- */
- if (p+1 < pvend && *(p+1) == '\0') {
- /* It's from fgets: we win! In particular,
- * we haven't done any mallocs yet, and can
- * build the final result on the first try.
- */
- ++p; /* include \n from fgets */
- }
- else {
- /* Must be from us: fgets didn't fill the
- * buffer and didn't find a newline, so it
- * must be the last and newline-free line of
- * the file.
- */
- assert(p > pvfree && *(p-1) == '\0');
- --p; /* don't include \0 from fgets */
- }
- v = PyString_FromStringAndSize(buf, p - buf);
- return v;
- }
- /* yuck: fgets overwrote all the newlines, i.e. the entire
- * buffer. So this line isn't over yet, or maybe it is but
- * we're exactly at EOF. If we haven't already, try using the
- * rest of the stack buffer.
- */
- assert(*(pvend-1) == '\0');
- if (pvfree == buf) {
- pvfree = pvend - 1; /* overwrite trailing null */
- total_v_size = MAXBUFSIZE;
- }
- else
- break;
- }
-
- /* The stack buffer isn't big enough; malloc a string object and read
- * into its buffer.
- */
- total_v_size = MAXBUFSIZE << 1;
- v = PyString_FromStringAndSize((char*)NULL, (int)total_v_size);
- if (v == NULL)
- return v;
- /* copy over everything except the last null byte */
- memcpy(BUF(v), buf, MAXBUFSIZE-1);
- pvfree = BUF(v) + MAXBUFSIZE - 1;
-
- /* Keep reading stuff into v; if it ever ends successfully, break
- * after setting p one beyond the end of the line. The code here is
- * very much like the code above, except reads into v's buffer; see
- * the code above for detailed comments about the logic.
- */
- for (;;) {
- Py_BEGIN_ALLOW_THREADS
- pvend = BUF(v) + total_v_size;
- nfree = pvend - pvfree;
- memset(pvfree, '\n', nfree);
- assert(nfree < INT_MAX);
- p = fgets(pvfree, (int)nfree, fp);
- Py_END_ALLOW_THREADS
-
- if (p == NULL) {
- clearerr(fp);
- if (PyErr_CheckSignals()) {
- Py_DECREF(v);
- return NULL;
- }
- p = pvfree;
- break;
- }
- p = memchr(pvfree, '\n', nfree);
- if (p != NULL) {
- if (p+1 < pvend && *(p+1) == '\0') {
- /* \n came from fgets */
- ++p;
- break;
- }
- /* \n came from us; last line of file, no newline */
- assert(p > pvfree && *(p-1) == '\0');
- --p;
- break;
- }
- /* expand buffer and try again */
- assert(*(pvend-1) == '\0');
- increment = total_v_size >> 2; /* mild exponential growth */
- prev_v_size = total_v_size;
- total_v_size += increment;
- /* check for overflow */
- if (total_v_size <= prev_v_size ||
- total_v_size > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "line is longer than a Python string can hold");
- Py_DECREF(v);
- return NULL;
- }
- if (_PyString_Resize(&v, (int)total_v_size) < 0)
- return NULL;
- /* overwrite the trailing null byte */
- pvfree = BUF(v) + (prev_v_size - 1);
- }
- if (BUF(v) + total_v_size != p)
- _PyString_Resize(&v, p - BUF(v));
- return v;
-#undef INITBUFSIZE
-#undef MAXBUFSIZE
-}
-#endif /* ifdef USE_FGETS_IN_GETLINE */
-
-/* Internal routine to get a line.
- Size argument interpretation:
- > 0: max length;
- <= 0: read arbitrary line
-*/
-
-static PyObject *
-get_line(PyFileObject *f, int n)
-{
- FILE *fp = f->f_fp;
- int c;
- char *buf, *end;
- size_t total_v_size; /* total # of slots in buffer */
- size_t used_v_size; /* # used slots in buffer */
- size_t increment; /* amount to increment the buffer */
- PyObject *v;
- int newlinetypes = f->f_newlinetypes;
- int skipnextlf = f->f_skipnextlf;
- int univ_newline = f->f_univ_newline;
-
-#if defined(USE_FGETS_IN_GETLINE)
- if (n <= 0 && !univ_newline )
- return getline_via_fgets(fp);
-#endif
- total_v_size = n > 0 ? n : 100;
- v = PyString_FromStringAndSize((char *)NULL, total_v_size);
- if (v == NULL)
- return NULL;
- buf = BUF(v);
- end = buf + total_v_size;
-
- for (;;) {
- Py_BEGIN_ALLOW_THREADS
- FLOCKFILE(fp);
- if (univ_newline) {
- c = 'x'; /* Shut up gcc warning */
- while ( buf != end && (c = GETC(fp)) != EOF ) {
- if (skipnextlf ) {
- skipnextlf = 0;
- if (c == '\n') {
- /* Seeing a \n here with
- * skipnextlf true means we
- * saw a \r before.
- */
- newlinetypes |= NEWLINE_CRLF;
- c = GETC(fp);
- if (c == EOF) break;
- } else {
- newlinetypes |= NEWLINE_CR;
- }
- }
- if (c == '\r') {
- skipnextlf = 1;
- c = '\n';
- } else if ( c == '\n')
- newlinetypes |= NEWLINE_LF;
- *buf++ = c;
- if (c == '\n') break;
- }
- if ( c == EOF && skipnextlf )
- newlinetypes |= NEWLINE_CR;
- } else /* If not universal newlines use the normal loop */
- while ((c = GETC(fp)) != EOF &&
- (*buf++ = c) != '\n' &&
- buf != end)
- ;
- FUNLOCKFILE(fp);
- Py_END_ALLOW_THREADS
- f->f_newlinetypes = newlinetypes;
- f->f_skipnextlf = skipnextlf;
- if (c == '\n')
- break;
- if (c == EOF) {
- if (ferror(fp)) {
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(fp);
- Py_DECREF(v);
- return NULL;
- }
- clearerr(fp);
- if (PyErr_CheckSignals()) {
- Py_DECREF(v);
- return NULL;
- }
- break;
- }
- /* Must be because buf == end */
- if (n > 0)
- break;
- used_v_size = total_v_size;
- increment = total_v_size >> 2; /* mild exponential growth */
- total_v_size += increment;
- if (total_v_size > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "line is longer than a Python string can hold");
- Py_DECREF(v);
- return NULL;
- }
- if (_PyString_Resize(&v, total_v_size) < 0)
- return NULL;
- buf = BUF(v) + used_v_size;
- end = BUF(v) + total_v_size;
- }
-
- used_v_size = buf - BUF(v);
- if (used_v_size != total_v_size)
- _PyString_Resize(&v, used_v_size);
- return v;
-}
-
-/* External C interface */
-
-PyObject *
-PyFile_GetLine(PyObject *f, int n)
-{
- PyObject *result;
-
- if (f == NULL) {
- PyErr_BadInternalCall();
- return NULL;
- }
-
- if (PyFile_Check(f)) {
- PyFileObject *fo = (PyFileObject *)f;
- if (fo->f_fp == NULL)
- return err_closed();
- /* refuse to mix with f.next() */
- if (fo->f_buf != NULL &&
- (fo->f_bufend - fo->f_bufptr) > 0 &&
- fo->f_buf[0] != '\0')
- return err_iterbuffered();
- result = get_line(fo, n);
- }
- else {
- PyObject *reader;
- PyObject *args;
-
- reader = PyObject_GetAttrString(f, "readline");
- if (reader == NULL)
- return NULL;
- if (n <= 0)
- args = PyTuple_New(0);
- else
- args = Py_BuildValue("(i)", n);
- if (args == NULL) {
- Py_DECREF(reader);
- return NULL;
- }
- result = PyEval_CallObject(reader, args);
- Py_DECREF(reader);
- Py_DECREF(args);
- if (result != NULL && !PyString_Check(result) &&
- !PyUnicode_Check(result)) {
- Py_DECREF(result);
- result = NULL;
- PyErr_SetString(PyExc_TypeError,
- "object.readline() returned non-string");
- }
- }
-
- if (n < 0 && result != NULL && PyString_Check(result)) {
- char *s = PyString_AS_STRING(result);
- Py_ssize_t len = PyString_GET_SIZE(result);
- if (len == 0) {
- Py_DECREF(result);
- result = NULL;
- PyErr_SetString(PyExc_EOFError,
- "EOF when reading a line");
- }
- else if (s[len-1] == '\n') {
- if (result->ob_refcnt == 1)
- _PyString_Resize(&result, len-1);
- else {
- PyObject *v;
- v = PyString_FromStringAndSize(s, len-1);
- Py_DECREF(result);
- result = v;
- }
- }
- }
-#ifdef Py_USING_UNICODE
- if (n < 0 && result != NULL && PyUnicode_Check(result)) {
- Py_UNICODE *s = PyUnicode_AS_UNICODE(result);
- Py_ssize_t len = PyUnicode_GET_SIZE(result);
- if (len == 0) {
- Py_DECREF(result);
- result = NULL;
- PyErr_SetString(PyExc_EOFError,
- "EOF when reading a line");
- }
- else if (s[len-1] == '\n') {
- if (result->ob_refcnt == 1)
- PyUnicode_Resize(&result, len-1);
- else {
- PyObject *v;
- v = PyUnicode_FromUnicode(s, len-1);
- Py_DECREF(result);
- result = v;
- }
- }
- }
-#endif
- return result;
-}
-
-/* Python method */
-
-static PyObject *
-file_readline(PyFileObject *f, PyObject *args)
-{
- int n = -1;
-
- if (f->f_fp == NULL)
- return err_closed();
- /* refuse to mix with f.next() */
- if (f->f_buf != NULL &&
- (f->f_bufend - f->f_bufptr) > 0 &&
- f->f_buf[0] != '\0')
- return err_iterbuffered();
- if (!PyArg_ParseTuple(args, "|i:readline", &n))
- return NULL;
- if (n == 0)
- return PyString_FromString("");
- if (n < 0)
- n = 0;
- return get_line(f, n);
-}
-
-static PyObject *
-file_readlines(PyFileObject *f, PyObject *args)
-{
- long sizehint = 0;
- PyObject *list;
- PyObject *line;
- char small_buffer[SMALLCHUNK];
- char *buffer = small_buffer;
- size_t buffersize = SMALLCHUNK;
- PyObject *big_buffer = NULL;
- size_t nfilled = 0;
- size_t nread;
- size_t totalread = 0;
- char *p, *q, *end;
- int err;
- int shortread = 0;
-
- if (f->f_fp == NULL)
- return err_closed();
- /* refuse to mix with f.next() */
- if (f->f_buf != NULL &&
- (f->f_bufend - f->f_bufptr) > 0 &&
- f->f_buf[0] != '\0')
- return err_iterbuffered();
- if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint))
- return NULL;
- if ((list = PyList_New(0)) == NULL)
- return NULL;
- for (;;) {
- if (shortread)
- nread = 0;
- else {
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- nread = Py_UniversalNewlineFread(buffer+nfilled,
- buffersize-nfilled, f->f_fp, (PyObject *)f);
- Py_END_ALLOW_THREADS
- shortread = (nread < buffersize-nfilled);
- }
- if (nread == 0) {
- sizehint = 0;
- if (!ferror(f->f_fp))
- break;
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- error:
- Py_DECREF(list);
- list = NULL;
- goto cleanup;
- }
- totalread += nread;
- p = (char *)memchr(buffer+nfilled, '\n', nread);
- if (p == NULL) {
- /* Need a larger buffer to fit this line */
- nfilled += nread;
- buffersize *= 2;
- if (buffersize > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "line is longer than a Python string can hold");
- goto error;
- }
- if (big_buffer == NULL) {
- /* Create the big buffer */
- big_buffer = PyString_FromStringAndSize(
- NULL, buffersize);
- if (big_buffer == NULL)
- goto error;
- buffer = PyString_AS_STRING(big_buffer);
- memcpy(buffer, small_buffer, nfilled);
- }
- else {
- /* Grow the big buffer */
- if ( _PyString_Resize(&big_buffer, buffersize) < 0 )
- goto error;
- buffer = PyString_AS_STRING(big_buffer);
- }
- continue;
- }
- end = buffer+nfilled+nread;
- q = buffer;
- do {
- /* Process complete lines */
- p++;
- line = PyString_FromStringAndSize(q, p-q);
- if (line == NULL)
- goto error;
- err = PyList_Append(list, line);
- Py_DECREF(line);
- if (err != 0)
- goto error;
- q = p;
- p = (char *)memchr(q, '\n', end-q);
- } while (p != NULL);
- /* Move the remaining incomplete line to the start */
- nfilled = end-q;
- memmove(buffer, q, nfilled);
- if (sizehint > 0)
- if (totalread >= (size_t)sizehint)
- break;
- }
- if (nfilled != 0) {
- /* Partial last line */
- line = PyString_FromStringAndSize(buffer, nfilled);
- if (line == NULL)
- goto error;
- if (sizehint > 0) {
- /* Need to complete the last line */
- PyObject *rest = get_line(f, 0);
- if (rest == NULL) {
- Py_DECREF(line);
- goto error;
- }
- PyString_Concat(&line, rest);
- Py_DECREF(rest);
- if (line == NULL)
- goto error;
- }
- err = PyList_Append(list, line);
- Py_DECREF(line);
- if (err != 0)
- goto error;
- }
- cleanup:
- Py_XDECREF(big_buffer);
- return list;
-}
-
-static PyObject *
-file_write(PyFileObject *f, PyObject *args)
-{
- char *s;
- Py_ssize_t n, n2;
- if (f->f_fp == NULL)
- return err_closed();
- if (!PyArg_ParseTuple(args, f->f_binary ? "s#" : "t#", &s, &n))
- return NULL;
- f->f_softspace = 0;
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- n2 = fwrite(s, 1, n, f->f_fp);
- Py_END_ALLOW_THREADS
- if (n2 != n) {
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- return NULL;
- }
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-file_writelines(PyFileObject *f, PyObject *seq)
-{
-#define CHUNKSIZE 1000
- PyObject *list, *line;
- PyObject *it; /* iter(seq) */
- PyObject *result;
- int index, islist;
- Py_ssize_t i, j, nwritten, len;
-
- assert(seq != NULL);
- if (f->f_fp == NULL)
- return err_closed();
-
- result = NULL;
- list = NULL;
- islist = PyList_Check(seq);
- if (islist)
- it = NULL;
- else {
- it = PyObject_GetIter(seq);
- if (it == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "writelines() requires an iterable argument");
- return NULL;
- }
- /* From here on, fail by going to error, to reclaim "it". */
- list = PyList_New(CHUNKSIZE);
- if (list == NULL)
- goto error;
- }
-
- /* Strategy: slurp CHUNKSIZE lines into a private list,
- checking that they are all strings, then write that list
- without holding the interpreter lock, then come back for more. */
- for (index = 0; ; index += CHUNKSIZE) {
- if (islist) {
- Py_XDECREF(list);
- list = PyList_GetSlice(seq, index, index+CHUNKSIZE);
- if (list == NULL)
- goto error;
- j = PyList_GET_SIZE(list);
- }
- else {
- for (j = 0; j < CHUNKSIZE; j++) {
- line = PyIter_Next(it);
- if (line == NULL) {
- if (PyErr_Occurred())
- goto error;
- break;
- }
- PyList_SetItem(list, j, line);
- }
- }
- if (j == 0)
- break;
-
- /* Check that all entries are indeed strings. If not,
- apply the same rules as for file.write() and
- convert the results to strings. This is slow, but
- seems to be the only way since all conversion APIs
- could potentially execute Python code. */
- for (i = 0; i < j; i++) {
- PyObject *v = PyList_GET_ITEM(list, i);
- if (!PyString_Check(v)) {
- const char *buffer;
- if (((f->f_binary &&
- PyObject_AsReadBuffer(v,
- (const void**)&buffer,
- &len)) ||
- PyObject_AsCharBuffer(v,
- &buffer,
- &len))) {
- PyErr_SetString(PyExc_TypeError,
- "writelines() argument must be a sequence of strings");
- goto error;
- }
- line = PyString_FromStringAndSize(buffer,
- len);
- if (line == NULL)
- goto error;
- Py_DECREF(v);
- PyList_SET_ITEM(list, i, line);
- }
- }
-
- /* Since we are releasing the global lock, the
- following code may *not* execute Python code. */
- Py_BEGIN_ALLOW_THREADS
- f->f_softspace = 0;
- errno = 0;
- for (i = 0; i < j; i++) {
- line = PyList_GET_ITEM(list, i);
- len = PyString_GET_SIZE(line);
- nwritten = fwrite(PyString_AS_STRING(line),
- 1, len, f->f_fp);
- if (nwritten != len) {
- Py_BLOCK_THREADS
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- goto error;
- }
- }
- Py_END_ALLOW_THREADS
-
- if (j < CHUNKSIZE)
- break;
- }
-
- Py_INCREF(Py_None);
- result = Py_None;
- error:
- Py_XDECREF(list);
- Py_XDECREF(it);
- return result;
-#undef CHUNKSIZE
-}
-
-static PyObject *
-file_self(PyFileObject *f)
-{
- if (f->f_fp == NULL)
- return err_closed();
- Py_INCREF(f);
- return (PyObject *)f;
-}
-
-static PyObject *
-file_exit(PyFileObject *f, PyObject *args)
-{
- PyObject *ret = file_close(f);
- if (!ret)
- /* If error occurred, pass through */
- return NULL;
- Py_DECREF(ret);
- /* We cannot return the result of close since a true
- * value will be interpreted as "yes, swallow the
- * exception if one was raised inside the with block". */
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(readline_doc,
-"readline([size]) -> next line from the file, as a string.\n"
-"\n"
-"Retain newline. A non-negative size argument limits the maximum\n"
-"number of bytes to return (an incomplete line may be returned then).\n"
-"Return an empty string at EOF.");
-
-PyDoc_STRVAR(read_doc,
-"read([size]) -> read at most size bytes, returned as a string.\n"
-"\n"
-"If the size argument is negative or omitted, read until EOF is reached.\n"
-"Notice that when in non-blocking mode, less data than what was requested\n"
-"may be returned, even if no size parameter was given.");
-
-PyDoc_STRVAR(write_doc,
-"write(str) -> None. Write string str to file.\n"
-"\n"
-"Note that due to buffering, flush() or close() may be needed before\n"
-"the file on disk reflects the data written.");
-
-PyDoc_STRVAR(fileno_doc,
-"fileno() -> integer \"file descriptor\".\n"
-"\n"
-"This is needed for lower-level file interfaces, such os.read().");
-
-PyDoc_STRVAR(seek_doc,
-"seek(offset[, whence]) -> None. Move to new file position.\n"
-"\n"
-"Argument offset is a byte count. Optional argument whence defaults to\n"
-"0 (offset from start of file, offset should be >= 0); other values are 1\n"
-"(move relative to current position, positive or negative), and 2 (move\n"
-"relative to end of file, usually negative, although many platforms allow\n"
-"seeking beyond the end of a file). If the file is opened in text mode,\n"
-"only offsets returned by tell() are legal. Use of other offsets causes\n"
-"undefined behavior."
-"\n"
-"Note that not all file objects are seekable.");
-
-#ifdef HAVE_FTRUNCATE
-PyDoc_STRVAR(truncate_doc,
-"truncate([size]) -> None. Truncate the file to at most size bytes.\n"
-"\n"
-"Size defaults to the current file position, as returned by tell().");
-#endif
-
-PyDoc_STRVAR(tell_doc,
-"tell() -> current file position, an integer (may be a long integer).");
-
-PyDoc_STRVAR(readinto_doc,
-"readinto() -> Undocumented. Don't use this; it may go away.");
-
-PyDoc_STRVAR(readlines_doc,
-"readlines([size]) -> list of strings, each a line from the file.\n"
-"\n"
-"Call readline() repeatedly and return a list of the lines so read.\n"
-"The optional size argument, if given, is an approximate bound on the\n"
-"total number of bytes in the lines returned.");
-
-PyDoc_STRVAR(xreadlines_doc,
-"xreadlines() -> returns self.\n"
-"\n"
-"For backward compatibility. File objects now include the performance\n"
-"optimizations previously implemented in the xreadlines module.");
-
-PyDoc_STRVAR(writelines_doc,
-"writelines(sequence_of_strings) -> None. Write the strings to the file.\n"
-"\n"
-"Note that newlines are not added. The sequence can be any iterable object\n"
-"producing strings. This is equivalent to calling write() for each string.");
-
-PyDoc_STRVAR(flush_doc,
-"flush() -> None. Flush the internal I/O buffer.");
-
-PyDoc_STRVAR(close_doc,
-"close() -> None or (perhaps) an integer. Close the file.\n"
-"\n"
-"Sets data attribute .closed to True. A closed file cannot be used for\n"
-"further I/O operations. close() may be called more than once without\n"
-"error. Some kinds of file objects (for example, opened by popen())\n"
-"may return an exit status upon closing.");
-
-PyDoc_STRVAR(isatty_doc,
-"isatty() -> true or false. True if the file is connected to a tty device.");
-
-PyDoc_STRVAR(enter_doc,
- "__enter__() -> self.");
-
-PyDoc_STRVAR(exit_doc,
- "__exit__(*excinfo) -> None. Closes the file.");
-
-static PyMethodDef file_methods[] = {
- {"readline", (PyCFunction)file_readline, METH_VARARGS, readline_doc},
- {"read", (PyCFunction)file_read, METH_VARARGS, read_doc},
- {"write", (PyCFunction)file_write, METH_VARARGS, write_doc},
- {"fileno", (PyCFunction)file_fileno, METH_NOARGS, fileno_doc},
- {"seek", (PyCFunction)file_seek, METH_VARARGS, seek_doc},
-#ifdef HAVE_FTRUNCATE
- {"truncate", (PyCFunction)file_truncate, METH_VARARGS, truncate_doc},
-#endif
- {"tell", (PyCFunction)file_tell, METH_NOARGS, tell_doc},
- {"readinto", (PyCFunction)file_readinto, METH_VARARGS, readinto_doc},
- {"readlines", (PyCFunction)file_readlines,METH_VARARGS, readlines_doc},
- {"xreadlines",(PyCFunction)file_self, METH_NOARGS, xreadlines_doc},
- {"writelines",(PyCFunction)file_writelines, METH_O, writelines_doc},
- {"flush", (PyCFunction)file_flush, METH_NOARGS, flush_doc},
- {"close", (PyCFunction)file_close, METH_NOARGS, close_doc},
- {"isatty", (PyCFunction)file_isatty, METH_NOARGS, isatty_doc},
- {"__enter__", (PyCFunction)file_self, METH_NOARGS, enter_doc},
- {"__exit__", (PyCFunction)file_exit, METH_VARARGS, exit_doc},
- {NULL, NULL} /* sentinel */
-};
-
-#define OFF(x) offsetof(PyFileObject, x)
-
-static PyMemberDef file_memberlist[] = {
- {"softspace", T_INT, OFF(f_softspace), 0,
- "flag indicating that a space needs to be printed; used by print"},
- {"mode", T_OBJECT, OFF(f_mode), RO,
- "file mode ('r', 'U', 'w', 'a', possibly with 'b' or '+' added)"},
- {"name", T_OBJECT, OFF(f_name), RO,
- "file name"},
- {"encoding", T_OBJECT, OFF(f_encoding), RO,
- "file encoding"},
- /* getattr(f, "closed") is implemented without this table */
- {NULL} /* Sentinel */
-};
-
-static PyObject *
-get_closed(PyFileObject *f, void *closure)
-{
- return PyBool_FromLong((long)(f->f_fp == 0));
-}
-static PyObject *
-get_newlines(PyFileObject *f, void *closure)
-{
- switch (f->f_newlinetypes) {
- case NEWLINE_UNKNOWN:
- Py_INCREF(Py_None);
- return Py_None;
- case NEWLINE_CR:
- return PyString_FromString("\r");
- case NEWLINE_LF:
- return PyString_FromString("\n");
- case NEWLINE_CR|NEWLINE_LF:
- return Py_BuildValue("(ss)", "\r", "\n");
- case NEWLINE_CRLF:
- return PyString_FromString("\r\n");
- case NEWLINE_CR|NEWLINE_CRLF:
- return Py_BuildValue("(ss)", "\r", "\r\n");
- case NEWLINE_LF|NEWLINE_CRLF:
- return Py_BuildValue("(ss)", "\n", "\r\n");
- case NEWLINE_CR|NEWLINE_LF|NEWLINE_CRLF:
- return Py_BuildValue("(sss)", "\r", "\n", "\r\n");
- default:
- PyErr_Format(PyExc_SystemError,
- "Unknown newlines value 0x%x\n",
- f->f_newlinetypes);
- return NULL;
- }
-}
-
-static PyGetSetDef file_getsetlist[] = {
- {"closed", (getter)get_closed, NULL, "True if the file is closed"},
- {"newlines", (getter)get_newlines, NULL,
- "end-of-line convention used in this file"},
- {0},
-};
-
-static void
-drop_readahead(PyFileObject *f)
-{
- if (f->f_buf != NULL) {
- PyMem_Free(f->f_buf);
- f->f_buf = NULL;
- }
-}
-
-/* Make sure that file has a readahead buffer with at least one byte
- (unless at EOF) and no more than bufsize. Returns negative value on
- error, will set MemoryError if bufsize bytes cannot be allocated. */
-static int
-readahead(PyFileObject *f, int bufsize)
-{
- Py_ssize_t chunksize;
-
- if (f->f_buf != NULL) {
- if( (f->f_bufend - f->f_bufptr) >= 1)
- return 0;
- else
- drop_readahead(f);
- }
- if ((f->f_buf = (char *)PyMem_Malloc(bufsize)) == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- Py_BEGIN_ALLOW_THREADS
- errno = 0;
- chunksize = Py_UniversalNewlineFread(
- f->f_buf, bufsize, f->f_fp, (PyObject *)f);
- Py_END_ALLOW_THREADS
- if (chunksize == 0) {
- if (ferror(f->f_fp)) {
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(f->f_fp);
- drop_readahead(f);
- return -1;
- }
- }
- f->f_bufptr = f->f_buf;
- f->f_bufend = f->f_buf + chunksize;
- return 0;
-}
-
-/* Used by file_iternext. The returned string will start with 'skip'
- uninitialized bytes followed by the remainder of the line. Don't be
- horrified by the recursive call: maximum recursion depth is limited by
- logarithmic buffer growth to about 50 even when reading a 1gb line. */
-
-static PyStringObject *
-readahead_get_line_skip(PyFileObject *f, int skip, int bufsize)
-{
- PyStringObject* s;
- char *bufptr;
- char *buf;
- Py_ssize_t len;
-
- if (f->f_buf == NULL)
- if (readahead(f, bufsize) < 0)
- return NULL;
-
- len = f->f_bufend - f->f_bufptr;
- if (len == 0)
- return (PyStringObject *)
- PyString_FromStringAndSize(NULL, skip);
- bufptr = (char *)memchr(f->f_bufptr, '\n', len);
- if (bufptr != NULL) {
- bufptr++; /* Count the '\n' */
- len = bufptr - f->f_bufptr;
- s = (PyStringObject *)
- PyString_FromStringAndSize(NULL, skip+len);
- if (s == NULL)
- return NULL;
- memcpy(PyString_AS_STRING(s)+skip, f->f_bufptr, len);
- f->f_bufptr = bufptr;
- if (bufptr == f->f_bufend)
- drop_readahead(f);
- } else {
- bufptr = f->f_bufptr;
- buf = f->f_buf;
- f->f_buf = NULL; /* Force new readahead buffer */
- assert(skip+len < INT_MAX);
- s = readahead_get_line_skip(
- f, (int)(skip+len), bufsize + (bufsize>>2) );
- if (s == NULL) {
- PyMem_Free(buf);
- return NULL;
- }
- memcpy(PyString_AS_STRING(s)+skip, bufptr, len);
- PyMem_Free(buf);
- }
- return s;
-}
-
-/* A larger buffer size may actually decrease performance. */
-#define READAHEAD_BUFSIZE 8192
-
-static PyObject *
-file_iternext(PyFileObject *f)
-{
- PyStringObject* l;
-
- if (f->f_fp == NULL)
- return err_closed();
-
- l = readahead_get_line_skip(f, 0, READAHEAD_BUFSIZE);
- if (l == NULL || PyString_GET_SIZE(l) == 0) {
- Py_XDECREF(l);
- return NULL;
- }
- return (PyObject *)l;
-}
-
-
-static PyObject *
-file_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *self;
- static PyObject *not_yet_string;
-
- assert(type != NULL && type->tp_alloc != NULL);
-
- if (not_yet_string == NULL) {
- not_yet_string = PyString_FromString("<uninitialized file>");
- if (not_yet_string == NULL)
- return NULL;
- }
-
- self = type->tp_alloc(type, 0);
- if (self != NULL) {
- /* Always fill in the name and mode, so that nobody else
- needs to special-case NULLs there. */
- Py_INCREF(not_yet_string);
- ((PyFileObject *)self)->f_name = not_yet_string;
- Py_INCREF(not_yet_string);
- ((PyFileObject *)self)->f_mode = not_yet_string;
- Py_INCREF(Py_None);
- ((PyFileObject *)self)->f_encoding = Py_None;
- ((PyFileObject *)self)->weakreflist = NULL;
- }
- return self;
-}
-
-static int
-file_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- PyFileObject *foself = (PyFileObject *)self;
- int ret = 0;
- static char *kwlist[] = {"name", "mode", "buffering", 0};
- char *name = NULL;
- char *mode = "r";
- int bufsize = -1;
- int wideargument = 0;
-
- assert(PyFile_Check(self));
- if (foself->f_fp != NULL) {
- /* Have to close the existing file first. */
- PyObject *closeresult = file_close(foself);
- if (closeresult == NULL)
- return -1;
- Py_DECREF(closeresult);
- }
-
-#ifdef Py_WIN_WIDE_FILENAMES
- if (GetVersion() < 0x80000000) { /* On NT, so wide API available */
- PyObject *po;
- if (PyArg_ParseTupleAndKeywords(args, kwds, "U|si:file",
- kwlist, &po, &mode, &bufsize)) {
- wideargument = 1;
- if (fill_file_fields(foself, NULL, po, mode,
- fclose) == NULL)
- goto Error;
- } else {
- /* Drop the argument parsing error as narrow
- strings are also valid. */
- PyErr_Clear();
- }
- }
-#endif
-
- if (!wideargument) {
- PyObject *o_name;
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|si:file", kwlist,
- Py_FileSystemDefaultEncoding,
- &name,
- &mode, &bufsize))
- return -1;
-
- /* We parse again to get the name as a PyObject */
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|si:file",
- kwlist, &o_name, &mode,
- &bufsize))
- goto Error;
-
- if (fill_file_fields(foself, NULL, o_name, mode,
- fclose) == NULL)
- goto Error;
- }
- if (open_the_file(foself, name, mode) == NULL)
- goto Error;
- foself->f_setbuf = NULL;
- PyFile_SetBufSize(self, bufsize);
- goto Done;
-
-Error:
- ret = -1;
- /* fall through */
-Done:
- PyMem_Free(name); /* free the encoded string */
- return ret;
-}
-
-PyDoc_VAR(file_doc) =
-PyDoc_STR(
-"file(name[, mode[, buffering]]) -> file object\n"
-"\n"
-"Open a file. The mode can be 'r', 'w' or 'a' for reading (default),\n"
-"writing or appending. The file will be created if it doesn't exist\n"
-"when opened for writing or appending; it will be truncated when\n"
-"opened for writing. Add a 'b' to the mode for binary files.\n"
-"Add a '+' to the mode to allow simultaneous reading and writing.\n"
-"If the buffering argument is given, 0 means unbuffered, 1 means line\n"
-"buffered, and larger numbers specify the buffer size.\n"
-)
-PyDoc_STR(
-"Add a 'U' to mode to open the file for input with universal newline\n"
-"support. Any line ending in the input file will be seen as a '\\n'\n"
-"in Python. Also, a file so opened gains the attribute 'newlines';\n"
-"the value for this attribute is one of None (no newline read yet),\n"
-"'\\r', '\\n', '\\r\\n' or a tuple containing all the newline types seen.\n"
-"\n"
-"'U' cannot be combined with 'w' or '+' mode.\n"
-);
-
-PyTypeObject PyFile_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "file",
- sizeof(PyFileObject),
- 0,
- (destructor)file_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)file_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- /* softspace is writable: we must supply tp_setattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_WEAKREFS, /* tp_flags */
- file_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(PyFileObject, weakreflist), /* tp_weaklistoffset */
- (getiterfunc)file_self, /* tp_iter */
- (iternextfunc)file_iternext, /* tp_iternext */
- file_methods, /* tp_methods */
- file_memberlist, /* tp_members */
- file_getsetlist, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- file_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- file_new, /* tp_new */
- PyObject_Del, /* tp_free */
-};
-
-/* Interface for the 'soft space' between print items. */
-
-int
-PyFile_SoftSpace(PyObject *f, int newflag)
-{
- long oldflag = 0;
- if (f == NULL) {
- /* Do nothing */
- }
- else if (PyFile_Check(f)) {
- oldflag = ((PyFileObject *)f)->f_softspace;
- ((PyFileObject *)f)->f_softspace = newflag;
- }
- else {
- PyObject *v;
- v = PyObject_GetAttrString(f, "softspace");
- if (v == NULL)
- PyErr_Clear();
- else {
- if (PyInt_Check(v))
- oldflag = PyInt_AsLong(v);
- assert(oldflag < INT_MAX);
- Py_DECREF(v);
- }
- v = PyInt_FromLong((long)newflag);
- if (v == NULL)
- PyErr_Clear();
- else {
- if (PyObject_SetAttrString(f, "softspace", v) != 0)
- PyErr_Clear();
- Py_DECREF(v);
- }
- }
- return (int)oldflag;
-}
-
-/* Interfaces to write objects/strings to file-like objects */
-
-int
-PyFile_WriteObject(PyObject *v, PyObject *f, int flags)
-{
- PyObject *writer, *value, *args, *result;
- if (f == NULL) {
- PyErr_SetString(PyExc_TypeError, "writeobject with NULL file");
- return -1;
- }
- else if (PyFile_Check(f)) {
- FILE *fp = PyFile_AsFile(f);
-#ifdef Py_USING_UNICODE
- PyObject *enc = ((PyFileObject*)f)->f_encoding;
- int result;
-#endif
- if (fp == NULL) {
- err_closed();
- return -1;
- }
-#ifdef Py_USING_UNICODE
- if ((flags & Py_PRINT_RAW) &&
- PyUnicode_Check(v) && enc != Py_None) {
- char *cenc = PyString_AS_STRING(enc);
- value = PyUnicode_AsEncodedString(v, cenc, "strict");
- if (value == NULL)
- return -1;
- } else {
- value = v;
- Py_INCREF(value);
- }
- result = PyObject_Print(value, fp, flags);
- Py_DECREF(value);
- return result;
-#else
- return PyObject_Print(v, fp, flags);
-#endif
- }
- writer = PyObject_GetAttrString(f, "write");
- if (writer == NULL)
- return -1;
- if (flags & Py_PRINT_RAW) {
- if (PyUnicode_Check(v)) {
- value = v;
- Py_INCREF(value);
- } else
- value = PyObject_Str(v);
- }
- else
- value = PyObject_Repr(v);
- if (value == NULL) {
- Py_DECREF(writer);
- return -1;
- }
- args = PyTuple_Pack(1, value);
- if (args == NULL) {
- Py_DECREF(value);
- Py_DECREF(writer);
- return -1;
- }
- result = PyEval_CallObject(writer, args);
- Py_DECREF(args);
- Py_DECREF(value);
- Py_DECREF(writer);
- if (result == NULL)
- return -1;
- Py_DECREF(result);
- return 0;
-}
-
-int
-PyFile_WriteString(const char *s, PyObject *f)
-{
- if (f == NULL) {
- /* Should be caused by a pre-existing error */
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_SystemError,
- "null file for PyFile_WriteString");
- return -1;
- }
- else if (PyFile_Check(f)) {
- FILE *fp = PyFile_AsFile(f);
- if (fp == NULL) {
- err_closed();
- return -1;
- }
- fputs(s, fp);
- return 0;
- }
- else if (!PyErr_Occurred()) {
- PyObject *v = PyString_FromString(s);
- int err;
- if (v == NULL)
- return -1;
- err = PyFile_WriteObject(v, f, Py_PRINT_RAW);
- Py_DECREF(v);
- return err;
- }
- else
- return -1;
-}
-
-/* Try to get a file-descriptor from a Python object. If the object
- is an integer or long integer, its value is returned. If not, the
- object's fileno() method is called if it exists; the method must return
- an integer or long integer, which is returned as the file descriptor value.
- -1 is returned on failure.
-*/
-
-int PyObject_AsFileDescriptor(PyObject *o)
-{
- int fd;
- PyObject *meth;
-
- if (PyInt_Check(o)) {
- fd = PyInt_AsLong(o);
- }
- else if (PyLong_Check(o)) {
- fd = PyLong_AsLong(o);
- }
- else if ((meth = PyObject_GetAttrString(o, "fileno")) != NULL)
- {
- PyObject *fno = PyEval_CallObject(meth, NULL);
- Py_DECREF(meth);
- if (fno == NULL)
- return -1;
-
- if (PyInt_Check(fno)) {
- fd = PyInt_AsLong(fno);
- Py_DECREF(fno);
- }
- else if (PyLong_Check(fno)) {
- fd = PyLong_AsLong(fno);
- Py_DECREF(fno);
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "fileno() returned a non-integer");
- Py_DECREF(fno);
- return -1;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "argument must be an int, or have a fileno() method.");
- return -1;
- }
-
- if (fd < 0) {
- PyErr_Format(PyExc_ValueError,
- "file descriptor cannot be a negative integer (%i)",
- fd);
- return -1;
- }
- return fd;
-}
-
-/* From here on we need access to the real fgets and fread */
-#undef fgets
-#undef fread
-
-/*
-** Py_UniversalNewlineFgets is an fgets variation that understands
-** all of \r, \n and \r\n conventions.
-** The stream should be opened in binary mode.
-** If fobj is NULL the routine always does newline conversion, and
-** it may peek one char ahead to gobble the second char in \r\n.
-** If fobj is non-NULL it must be a PyFileObject. In this case there
-** is no readahead but in stead a flag is used to skip a following
-** \n on the next read. Also, if the file is open in binary mode
-** the whole conversion is skipped. Finally, the routine keeps track of
-** the different types of newlines seen.
-** Note that we need no error handling: fgets() treats error and eof
-** identically.
-*/
-char *
-Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
-{
- char *p = buf;
- int c;
- int newlinetypes = 0;
- int skipnextlf = 0;
- int univ_newline = 1;
-
- if (fobj) {
- if (!PyFile_Check(fobj)) {
- errno = ENXIO; /* What can you do... */
- return NULL;
- }
- univ_newline = ((PyFileObject *)fobj)->f_univ_newline;
- if ( !univ_newline )
- return fgets(buf, n, stream);
- newlinetypes = ((PyFileObject *)fobj)->f_newlinetypes;
- skipnextlf = ((PyFileObject *)fobj)->f_skipnextlf;
- }
- FLOCKFILE(stream);
- c = 'x'; /* Shut up gcc warning */
- while (--n > 0 && (c = GETC(stream)) != EOF ) {
- if (skipnextlf ) {
- skipnextlf = 0;
- if (c == '\n') {
- /* Seeing a \n here with skipnextlf true
- ** means we saw a \r before.
- */
- newlinetypes |= NEWLINE_CRLF;
- c = GETC(stream);
- if (c == EOF) break;
- } else {
- /*
- ** Note that c == EOF also brings us here,
- ** so we're okay if the last char in the file
- ** is a CR.
- */
- newlinetypes |= NEWLINE_CR;
- }
- }
- if (c == '\r') {
- /* A \r is translated into a \n, and we skip
- ** an adjacent \n, if any. We don't set the
- ** newlinetypes flag until we've seen the next char.
- */
- skipnextlf = 1;
- c = '\n';
- } else if ( c == '\n') {
- newlinetypes |= NEWLINE_LF;
- }
- *p++ = c;
- if (c == '\n') break;
- }
- if ( c == EOF && skipnextlf )
- newlinetypes |= NEWLINE_CR;
- FUNLOCKFILE(stream);
- *p = '\0';
- if (fobj) {
- ((PyFileObject *)fobj)->f_newlinetypes = newlinetypes;
- ((PyFileObject *)fobj)->f_skipnextlf = skipnextlf;
- } else if ( skipnextlf ) {
- /* If we have no file object we cannot save the
- ** skipnextlf flag. We have to readahead, which
- ** will cause a pause if we're reading from an
- ** interactive stream, but that is very unlikely
- ** unless we're doing something silly like
- ** execfile("/dev/tty").
- */
- c = GETC(stream);
- if ( c != '\n' )
- ungetc(c, stream);
- }
- if (p == buf)
- return NULL;
- return buf;
-}
-
-/*
-** Py_UniversalNewlineFread is an fread variation that understands
-** all of \r, \n and \r\n conventions.
-** The stream should be opened in binary mode.
-** fobj must be a PyFileObject. In this case there
-** is no readahead but in stead a flag is used to skip a following
-** \n on the next read. Also, if the file is open in binary mode
-** the whole conversion is skipped. Finally, the routine keeps track of
-** the different types of newlines seen.
-*/
-size_t
-Py_UniversalNewlineFread(char *buf, size_t n,
- FILE *stream, PyObject *fobj)
-{
- char *dst = buf;
- PyFileObject *f = (PyFileObject *)fobj;
- int newlinetypes, skipnextlf;
-
- assert(buf != NULL);
- assert(stream != NULL);
-
- if (!fobj || !PyFile_Check(fobj)) {
- errno = ENXIO; /* What can you do... */
- return 0;
- }
- if (!f->f_univ_newline)
- return fread(buf, 1, n, stream);
- newlinetypes = f->f_newlinetypes;
- skipnextlf = f->f_skipnextlf;
- /* Invariant: n is the number of bytes remaining to be filled
- * in the buffer.
- */
- while (n) {
- size_t nread;
- int shortread;
- char *src = dst;
-
- nread = fread(dst, 1, n, stream);
- assert(nread <= n);
- if (nread == 0)
- break;
-
- n -= nread; /* assuming 1 byte out for each in; will adjust */
- shortread = n != 0; /* true iff EOF or error */
- while (nread--) {
- char c = *src++;
- if (c == '\r') {
- /* Save as LF and set flag to skip next LF. */
- *dst++ = '\n';
- skipnextlf = 1;
- }
- else if (skipnextlf && c == '\n') {
- /* Skip LF, and remember we saw CR LF. */
- skipnextlf = 0;
- newlinetypes |= NEWLINE_CRLF;
- ++n;
- }
- else {
- /* Normal char to be stored in buffer. Also
- * update the newlinetypes flag if either this
- * is an LF or the previous char was a CR.
- */
- if (c == '\n')
- newlinetypes |= NEWLINE_LF;
- else if (skipnextlf)
- newlinetypes |= NEWLINE_CR;
- *dst++ = c;
- skipnextlf = 0;
- }
- }
- if (shortread) {
- /* If this is EOF, update type flags. */
- if (skipnextlf && feof(stream))
- newlinetypes |= NEWLINE_CR;
- break;
- }
- }
- f->f_newlinetypes = newlinetypes;
- f->f_skipnextlf = skipnextlf;
- return dst - buf;
-}
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/sys/src/cmd/python/Objects/floatobject.c b/sys/src/cmd/python/Objects/floatobject.c
deleted file mode 100644
index 2087ceba8..000000000
--- a/sys/src/cmd/python/Objects/floatobject.c
+++ /dev/null
@@ -1,1748 +0,0 @@
-
-/* Float object implementation */
-
-/* XXX There should be overflow checks here, but it's hard to check
- for any kind of float exception without losing portability. */
-
-#include "Python.h"
-
-#include <ctype.h>
-
-#if !defined(__STDC__)
-extern double fmod(double, double);
-extern double pow(double, double);
-#endif
-
-/* Special free list -- see comments for same code in intobject.c. */
-#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
-#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */
-#define N_FLOATOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject))
-
-struct _floatblock {
- struct _floatblock *next;
- PyFloatObject objects[N_FLOATOBJECTS];
-};
-
-typedef struct _floatblock PyFloatBlock;
-
-static PyFloatBlock *block_list = NULL;
-static PyFloatObject *free_list = NULL;
-
-static PyFloatObject *
-fill_free_list(void)
-{
- PyFloatObject *p, *q;
- /* XXX Float blocks escape the object heap. Use PyObject_MALLOC ??? */
- p = (PyFloatObject *) PyMem_MALLOC(sizeof(PyFloatBlock));
- if (p == NULL)
- return (PyFloatObject *) PyErr_NoMemory();
- ((PyFloatBlock *)p)->next = block_list;
- block_list = (PyFloatBlock *)p;
- p = &((PyFloatBlock *)p)->objects[0];
- q = p + N_FLOATOBJECTS;
- while (--q > p)
- q->ob_type = (struct _typeobject *)(q-1);
- q->ob_type = NULL;
- return p + N_FLOATOBJECTS - 1;
-}
-
-PyObject *
-PyFloat_FromDouble(double fval)
-{
- register PyFloatObject *op;
- if (free_list == NULL) {
- if ((free_list = fill_free_list()) == NULL)
- return NULL;
- }
- /* Inline PyObject_New */
- op = free_list;
- free_list = (PyFloatObject *)op->ob_type;
- PyObject_INIT(op, &PyFloat_Type);
- op->ob_fval = fval;
- return (PyObject *) op;
-}
-
-/**************************************************************************
-RED_FLAG 22-Sep-2000 tim
-PyFloat_FromString's pend argument is braindead. Prior to this RED_FLAG,
-
-1. If v was a regular string, *pend was set to point to its terminating
- null byte. That's useless (the caller can find that without any
- help from this function!).
-
-2. If v was a Unicode string, or an object convertible to a character
- buffer, *pend was set to point into stack trash (the auto temp
- vector holding the character buffer). That was downright dangerous.
-
-Since we can't change the interface of a public API function, pend is
-still supported but now *officially* useless: if pend is not NULL,
-*pend is set to NULL.
-**************************************************************************/
-PyObject *
-PyFloat_FromString(PyObject *v, char **pend)
-{
- const char *s, *last, *end;
- double x;
- char buffer[256]; /* for errors */
-#ifdef Py_USING_UNICODE
- char s_buffer[256]; /* for objects convertible to a char buffer */
-#endif
- Py_ssize_t len;
-
- if (pend)
- *pend = NULL;
- if (PyString_Check(v)) {
- s = PyString_AS_STRING(v);
- len = PyString_GET_SIZE(v);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(v)) {
- if (PyUnicode_GET_SIZE(v) >= (Py_ssize_t)sizeof(s_buffer)) {
- PyErr_SetString(PyExc_ValueError,
- "Unicode float() literal too long to convert");
- return NULL;
- }
- if (PyUnicode_EncodeDecimal(PyUnicode_AS_UNICODE(v),
- PyUnicode_GET_SIZE(v),
- s_buffer,
- NULL))
- return NULL;
- s = s_buffer;
- len = strlen(s);
- }
-#endif
- else if (PyObject_AsCharBuffer(v, &s, &len)) {
- PyErr_SetString(PyExc_TypeError,
- "float() argument must be a string or a number");
- return NULL;
- }
-
- last = s + len;
- while (*s && isspace(Py_CHARMASK(*s)))
- s++;
- if (*s == '\0') {
- PyErr_SetString(PyExc_ValueError, "empty string for float()");
- return NULL;
- }
- /* We don't care about overflow or underflow. If the platform supports
- * them, infinities and signed zeroes (on underflow) are fine.
- * However, strtod can return 0 for denormalized numbers, where atof
- * does not. So (alas!) we special-case a zero result. Note that
- * whether strtod sets errno on underflow is not defined, so we can't
- * key off errno.
- */
- PyFPE_START_PROTECT("strtod", return NULL)
- x = PyOS_ascii_strtod(s, (char **)&end);
- PyFPE_END_PROTECT(x)
- errno = 0;
- /* Believe it or not, Solaris 2.6 can move end *beyond* the null
- byte at the end of the string, when the input is inf(inity). */
- if (end > last)
- end = last;
- if (end == s) {
- PyOS_snprintf(buffer, sizeof(buffer),
- "invalid literal for float(): %.200s", s);
- PyErr_SetString(PyExc_ValueError, buffer);
- return NULL;
- }
- /* Since end != s, the platform made *some* kind of sense out
- of the input. Trust it. */
- while (*end && isspace(Py_CHARMASK(*end)))
- end++;
- if (*end != '\0') {
- PyOS_snprintf(buffer, sizeof(buffer),
- "invalid literal for float(): %.200s", s);
- PyErr_SetString(PyExc_ValueError, buffer);
- return NULL;
- }
- else if (end != last) {
- PyErr_SetString(PyExc_ValueError,
- "null byte in argument for float()");
- return NULL;
- }
- if (x == 0.0) {
- /* See above -- may have been strtod being anal
- about denorms. */
- PyFPE_START_PROTECT("atof", return NULL)
- x = PyOS_ascii_atof(s);
- PyFPE_END_PROTECT(x)
- errno = 0; /* whether atof ever set errno is undefined */
- }
- return PyFloat_FromDouble(x);
-}
-
-static void
-float_dealloc(PyFloatObject *op)
-{
- if (PyFloat_CheckExact(op)) {
- op->ob_type = (struct _typeobject *)free_list;
- free_list = op;
- }
- else
- op->ob_type->tp_free((PyObject *)op);
-}
-
-double
-PyFloat_AsDouble(PyObject *op)
-{
- PyNumberMethods *nb;
- PyFloatObject *fo;
- double val;
-
- if (op && PyFloat_Check(op))
- return PyFloat_AS_DOUBLE((PyFloatObject*) op);
-
- if (op == NULL) {
- PyErr_BadArgument();
- return -1;
- }
-
- if ((nb = op->ob_type->tp_as_number) == NULL || nb->nb_float == NULL) {
- PyErr_SetString(PyExc_TypeError, "a float is required");
- return -1;
- }
-
- fo = (PyFloatObject*) (*nb->nb_float) (op);
- if (fo == NULL)
- return -1;
- if (!PyFloat_Check(fo)) {
- PyErr_SetString(PyExc_TypeError,
- "nb_float should return float object");
- return -1;
- }
-
- val = PyFloat_AS_DOUBLE(fo);
- Py_DECREF(fo);
-
- return val;
-}
-
-/* Methods */
-
-static void
-format_float(char *buf, size_t buflen, PyFloatObject *v, int precision)
-{
- register char *cp;
- char format[32];
- /* Subroutine for float_repr and float_print.
- We want float numbers to be recognizable as such,
- i.e., they should contain a decimal point or an exponent.
- However, %g may print the number as an integer;
- in such cases, we append ".0" to the string. */
-
- assert(PyFloat_Check(v));
- PyOS_snprintf(format, 32, "%%.%ig", precision);
- PyOS_ascii_formatd(buf, buflen, format, v->ob_fval);
- cp = buf;
- if (*cp == '-')
- cp++;
- for (; *cp != '\0'; cp++) {
- /* Any non-digit means it's not an integer;
- this takes care of NAN and INF as well. */
- if (!isdigit(Py_CHARMASK(*cp)))
- break;
- }
- if (*cp == '\0') {
- *cp++ = '.';
- *cp++ = '0';
- *cp++ = '\0';
- }
-}
-
-/* XXX PyFloat_AsStringEx should not be a public API function (for one
- XXX thing, its signature passes a buffer without a length; for another,
- XXX it isn't useful outside this file).
-*/
-void
-PyFloat_AsStringEx(char *buf, PyFloatObject *v, int precision)
-{
- format_float(buf, 100, v, precision);
-}
-
-/* Macro and helper that convert PyObject obj to a C double and store
- the value in dbl; this replaces the functionality of the coercion
- slot function. If conversion to double raises an exception, obj is
- set to NULL, and the function invoking this macro returns NULL. If
- obj is not of float, int or long type, Py_NotImplemented is incref'ed,
- stored in obj, and returned from the function invoking this macro.
-*/
-#define CONVERT_TO_DOUBLE(obj, dbl) \
- if (PyFloat_Check(obj)) \
- dbl = PyFloat_AS_DOUBLE(obj); \
- else if (convert_to_double(&(obj), &(dbl)) < 0) \
- return obj;
-
-static int
-convert_to_double(PyObject **v, double *dbl)
-{
- register PyObject *obj = *v;
-
- if (PyInt_Check(obj)) {
- *dbl = (double)PyInt_AS_LONG(obj);
- }
- else if (PyLong_Check(obj)) {
- *dbl = PyLong_AsDouble(obj);
- if (*dbl == -1.0 && PyErr_Occurred()) {
- *v = NULL;
- return -1;
- }
- }
- else {
- Py_INCREF(Py_NotImplemented);
- *v = Py_NotImplemented;
- return -1;
- }
- return 0;
-}
-
-/* Precisions used by repr() and str(), respectively.
-
- The repr() precision (17 significant decimal digits) is the minimal number
- that is guaranteed to have enough precision so that if the number is read
- back in the exact same binary value is recreated. This is true for IEEE
- floating point by design, and also happens to work for all other modern
- hardware.
-
- The str() precision is chosen so that in most cases, the rounding noise
- created by various operations is suppressed, while giving plenty of
- precision for practical use.
-
-*/
-
-#define PREC_REPR 17
-#define PREC_STR 12
-
-/* XXX PyFloat_AsString and PyFloat_AsReprString should be deprecated:
- XXX they pass a char buffer without passing a length.
-*/
-void
-PyFloat_AsString(char *buf, PyFloatObject *v)
-{
- format_float(buf, 100, v, PREC_STR);
-}
-
-void
-PyFloat_AsReprString(char *buf, PyFloatObject *v)
-{
- format_float(buf, 100, v, PREC_REPR);
-}
-
-/* ARGSUSED */
-static int
-float_print(PyFloatObject *v, FILE *fp, int flags)
-{
- char buf[100];
- format_float(buf, sizeof(buf), v,
- (flags & Py_PRINT_RAW) ? PREC_STR : PREC_REPR);
- fputs(buf, fp);
- return 0;
-}
-
-static PyObject *
-float_repr(PyFloatObject *v)
-{
- char buf[100];
- format_float(buf, sizeof(buf), v, PREC_REPR);
- return PyString_FromString(buf);
-}
-
-static PyObject *
-float_str(PyFloatObject *v)
-{
- char buf[100];
- format_float(buf, sizeof(buf), v, PREC_STR);
- return PyString_FromString(buf);
-}
-
-/* Comparison is pretty much a nightmare. When comparing float to float,
- * we do it as straightforwardly (and long-windedly) as conceivable, so
- * that, e.g., Python x == y delivers the same result as the platform
- * C x == y when x and/or y is a NaN.
- * When mixing float with an integer type, there's no good *uniform* approach.
- * Converting the double to an integer obviously doesn't work, since we
- * may lose info from fractional bits. Converting the integer to a double
- * also has two failure modes: (1) a long int may trigger overflow (too
- * large to fit in the dynamic range of a C double); (2) even a C long may have
- * more bits than fit in a C double (e.g., on a a 64-bit box long may have
- * 63 bits of precision, but a C double probably has only 53), and then
- * we can falsely claim equality when low-order integer bits are lost by
- * coercion to double. So this part is painful too.
- */
-
-static PyObject*
-float_richcompare(PyObject *v, PyObject *w, int op)
-{
- double i, j;
- int r = 0;
-
- assert(PyFloat_Check(v));
- i = PyFloat_AS_DOUBLE(v);
-
- /* Switch on the type of w. Set i and j to doubles to be compared,
- * and op to the richcomp to use.
- */
- if (PyFloat_Check(w))
- j = PyFloat_AS_DOUBLE(w);
-
- else if (!Py_IS_FINITE(i)) {
- if (PyInt_Check(w) || PyLong_Check(w))
- /* If i is an infinity, its magnitude exceeds any
- * finite integer, so it doesn't matter which int we
- * compare i with. If i is a NaN, similarly.
- */
- j = 0.0;
- else
- goto Unimplemented;
- }
-
- else if (PyInt_Check(w)) {
- long jj = PyInt_AS_LONG(w);
- /* In the worst realistic case I can imagine, C double is a
- * Cray single with 48 bits of precision, and long has 64
- * bits.
- */
-#if SIZEOF_LONG > 6
- unsigned long abs = (unsigned long)(jj < 0 ? -jj : jj);
- if (abs >> 48) {
- /* Needs more than 48 bits. Make it take the
- * PyLong path.
- */
- PyObject *result;
- PyObject *ww = PyLong_FromLong(jj);
-
- if (ww == NULL)
- return NULL;
- result = float_richcompare(v, ww, op);
- Py_DECREF(ww);
- return result;
- }
-#endif
- j = (double)jj;
- assert((long)j == jj);
- }
-
- else if (PyLong_Check(w)) {
- int vsign = i == 0.0 ? 0 : i < 0.0 ? -1 : 1;
- int wsign = _PyLong_Sign(w);
- size_t nbits;
- int exponent;
-
- if (vsign != wsign) {
- /* Magnitudes are irrelevant -- the signs alone
- * determine the outcome.
- */
- i = (double)vsign;
- j = (double)wsign;
- goto Compare;
- }
- /* The signs are the same. */
- /* Convert w to a double if it fits. In particular, 0 fits. */
- nbits = _PyLong_NumBits(w);
- if (nbits == (size_t)-1 && PyErr_Occurred()) {
- /* This long is so large that size_t isn't big enough
- * to hold the # of bits. Replace with little doubles
- * that give the same outcome -- w is so large that
- * its magnitude must exceed the magnitude of any
- * finite float.
- */
- PyErr_Clear();
- i = (double)vsign;
- assert(wsign != 0);
- j = wsign * 2.0;
- goto Compare;
- }
- if (nbits <= 48) {
- j = PyLong_AsDouble(w);
- /* It's impossible that <= 48 bits overflowed. */
- assert(j != -1.0 || ! PyErr_Occurred());
- goto Compare;
- }
- assert(wsign != 0); /* else nbits was 0 */
- assert(vsign != 0); /* if vsign were 0, then since wsign is
- * not 0, we would have taken the
- * vsign != wsign branch at the start */
- /* We want to work with non-negative numbers. */
- if (vsign < 0) {
- /* "Multiply both sides" by -1; this also swaps the
- * comparator.
- */
- i = -i;
- op = _Py_SwappedOp[op];
- }
- assert(i > 0.0);
- (void) frexp(i, &exponent);
- /* exponent is the # of bits in v before the radix point;
- * we know that nbits (the # of bits in w) > 48 at this point
- */
- if (exponent < 0 || (size_t)exponent < nbits) {
- i = 1.0;
- j = 2.0;
- goto Compare;
- }
- if ((size_t)exponent > nbits) {
- i = 2.0;
- j = 1.0;
- goto Compare;
- }
- /* v and w have the same number of bits before the radix
- * point. Construct two longs that have the same comparison
- * outcome.
- */
- {
- double fracpart;
- double intpart;
- PyObject *result = NULL;
- PyObject *one = NULL;
- PyObject *vv = NULL;
- PyObject *ww = w;
-
- if (wsign < 0) {
- ww = PyNumber_Negative(w);
- if (ww == NULL)
- goto Error;
- }
- else
- Py_INCREF(ww);
-
- fracpart = modf(i, &intpart);
- vv = PyLong_FromDouble(intpart);
- if (vv == NULL)
- goto Error;
-
- if (fracpart != 0.0) {
- /* Shift left, and or a 1 bit into vv
- * to represent the lost fraction.
- */
- PyObject *temp;
-
- one = PyInt_FromLong(1);
- if (one == NULL)
- goto Error;
-
- temp = PyNumber_Lshift(ww, one);
- if (temp == NULL)
- goto Error;
- Py_DECREF(ww);
- ww = temp;
-
- temp = PyNumber_Lshift(vv, one);
- if (temp == NULL)
- goto Error;
- Py_DECREF(vv);
- vv = temp;
-
- temp = PyNumber_Or(vv, one);
- if (temp == NULL)
- goto Error;
- Py_DECREF(vv);
- vv = temp;
- }
-
- r = PyObject_RichCompareBool(vv, ww, op);
- if (r < 0)
- goto Error;
- result = PyBool_FromLong(r);
- Error:
- Py_XDECREF(vv);
- Py_XDECREF(ww);
- Py_XDECREF(one);
- return result;
- }
- } /* else if (PyLong_Check(w)) */
-
- else /* w isn't float, int, or long */
- goto Unimplemented;
-
- Compare:
- PyFPE_START_PROTECT("richcompare", return NULL)
- switch (op) {
- case Py_EQ:
- r = i == j;
- break;
- case Py_NE:
- r = i != j;
- break;
- case Py_LE:
- r = i <= j;
- break;
- case Py_GE:
- r = i >= j;
- break;
- case Py_LT:
- r = i < j;
- break;
- case Py_GT:
- r = i > j;
- break;
- }
- PyFPE_END_PROTECT(r)
- return PyBool_FromLong(r);
-
- Unimplemented:
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-static long
-float_hash(PyFloatObject *v)
-{
- return _Py_HashDouble(v->ob_fval);
-}
-
-static PyObject *
-float_add(PyObject *v, PyObject *w)
-{
- double a,b;
- CONVERT_TO_DOUBLE(v, a);
- CONVERT_TO_DOUBLE(w, b);
- PyFPE_START_PROTECT("add", return 0)
- a = a + b;
- PyFPE_END_PROTECT(a)
- return PyFloat_FromDouble(a);
-}
-
-static PyObject *
-float_sub(PyObject *v, PyObject *w)
-{
- double a,b;
- CONVERT_TO_DOUBLE(v, a);
- CONVERT_TO_DOUBLE(w, b);
- PyFPE_START_PROTECT("subtract", return 0)
- a = a - b;
- PyFPE_END_PROTECT(a)
- return PyFloat_FromDouble(a);
-}
-
-static PyObject *
-float_mul(PyObject *v, PyObject *w)
-{
- double a,b;
- CONVERT_TO_DOUBLE(v, a);
- CONVERT_TO_DOUBLE(w, b);
- PyFPE_START_PROTECT("multiply", return 0)
- a = a * b;
- PyFPE_END_PROTECT(a)
- return PyFloat_FromDouble(a);
-}
-
-static PyObject *
-float_div(PyObject *v, PyObject *w)
-{
- double a,b;
- CONVERT_TO_DOUBLE(v, a);
- CONVERT_TO_DOUBLE(w, b);
- if (b == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float division");
- return NULL;
- }
- PyFPE_START_PROTECT("divide", return 0)
- a = a / b;
- PyFPE_END_PROTECT(a)
- return PyFloat_FromDouble(a);
-}
-
-static PyObject *
-float_classic_div(PyObject *v, PyObject *w)
-{
- double a,b;
- CONVERT_TO_DOUBLE(v, a);
- CONVERT_TO_DOUBLE(w, b);
- if (Py_DivisionWarningFlag >= 2 &&
- PyErr_Warn(PyExc_DeprecationWarning, "classic float division") < 0)
- return NULL;
- if (b == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float division");
- return NULL;
- }
- PyFPE_START_PROTECT("divide", return 0)
- a = a / b;
- PyFPE_END_PROTECT(a)
- return PyFloat_FromDouble(a);
-}
-
-static PyObject *
-float_rem(PyObject *v, PyObject *w)
-{
- double vx, wx;
- double mod;
- CONVERT_TO_DOUBLE(v, vx);
- CONVERT_TO_DOUBLE(w, wx);
- if (wx == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float modulo");
- return NULL;
- }
- PyFPE_START_PROTECT("modulo", return 0)
- mod = fmod(vx, wx);
- /* note: checking mod*wx < 0 is incorrect -- underflows to
- 0 if wx < sqrt(smallest nonzero double) */
- if (mod && ((wx < 0) != (mod < 0))) {
- mod += wx;
- }
- PyFPE_END_PROTECT(mod)
- return PyFloat_FromDouble(mod);
-}
-
-static PyObject *
-float_divmod(PyObject *v, PyObject *w)
-{
- double vx, wx;
- double div, mod, floordiv;
- CONVERT_TO_DOUBLE(v, vx);
- CONVERT_TO_DOUBLE(w, wx);
- if (wx == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
- return NULL;
- }
- PyFPE_START_PROTECT("divmod", return 0)
- mod = fmod(vx, wx);
- /* fmod is typically exact, so vx-mod is *mathematically* an
- exact multiple of wx. But this is fp arithmetic, and fp
- vx - mod is an approximation; the result is that div may
- not be an exact integral value after the division, although
- it will always be very close to one.
- */
- div = (vx - mod) / wx;
- if (mod) {
- /* ensure the remainder has the same sign as the denominator */
- if ((wx < 0) != (mod < 0)) {
- mod += wx;
- div -= 1.0;
- }
- }
- else {
- /* the remainder is zero, and in the presence of signed zeroes
- fmod returns different results across platforms; ensure
- it has the same sign as the denominator; we'd like to do
- "mod = wx * 0.0", but that may get optimized away */
- mod *= mod; /* hide "mod = +0" from optimizer */
- if (wx < 0.0)
- mod = -mod;
- }
- /* snap quotient to nearest integral value */
- if (div) {
- floordiv = floor(div);
- if (div - floordiv > 0.5)
- floordiv += 1.0;
- }
- else {
- /* div is zero - get the same sign as the true quotient */
- div *= div; /* hide "div = +0" from optimizers */
- floordiv = div * vx / wx; /* zero w/ sign of vx/wx */
- }
- PyFPE_END_PROTECT(floordiv)
- return Py_BuildValue("(dd)", floordiv, mod);
-}
-
-static PyObject *
-float_floor_div(PyObject *v, PyObject *w)
-{
- PyObject *t, *r;
-
- t = float_divmod(v, w);
- if (t == NULL || t == Py_NotImplemented)
- return t;
- assert(PyTuple_CheckExact(t));
- r = PyTuple_GET_ITEM(t, 0);
- Py_INCREF(r);
- Py_DECREF(t);
- return r;
-}
-
-static PyObject *
-float_pow(PyObject *v, PyObject *w, PyObject *z)
-{
- double iv, iw, ix;
-
- if ((PyObject *)z != Py_None) {
- PyErr_SetString(PyExc_TypeError, "pow() 3rd argument not "
- "allowed unless all arguments are integers");
- return NULL;
- }
-
- CONVERT_TO_DOUBLE(v, iv);
- CONVERT_TO_DOUBLE(w, iw);
-
- /* Sort out special cases here instead of relying on pow() */
- if (iw == 0) { /* v**0 is 1, even 0**0 */
- PyFPE_START_PROTECT("pow", return NULL)
- if ((PyObject *)z != Py_None) {
- double iz;
- CONVERT_TO_DOUBLE(z, iz);
- ix = fmod(1.0, iz);
- if (ix != 0 && iz < 0)
- ix += iz;
- }
- else
- ix = 1.0;
- PyFPE_END_PROTECT(ix)
- return PyFloat_FromDouble(ix);
- }
- if (iv == 0.0) { /* 0**w is error if w<0, else 1 */
- if (iw < 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError,
- "0.0 cannot be raised to a negative power");
- return NULL;
- }
- return PyFloat_FromDouble(0.0);
- }
- if (iv < 0.0) {
- /* Whether this is an error is a mess, and bumps into libm
- * bugs so we have to figure it out ourselves.
- */
- if (iw != floor(iw)) {
- PyErr_SetString(PyExc_ValueError, "negative number "
- "cannot be raised to a fractional power");
- return NULL;
- }
- /* iw is an exact integer, albeit perhaps a very large one.
- * -1 raised to an exact integer should never be exceptional.
- * Alas, some libms (chiefly glibc as of early 2003) return
- * NaN and set EDOM on pow(-1, large_int) if the int doesn't
- * happen to be representable in a *C* integer. That's a
- * bug; we let that slide in math.pow() (which currently
- * reflects all platform accidents), but not for Python's **.
- */
- if (iv == -1.0 && Py_IS_FINITE(iw)) {
- /* Return 1 if iw is even, -1 if iw is odd; there's
- * no guarantee that any C integral type is big
- * enough to hold iw, so we have to check this
- * indirectly.
- */
- ix = floor(iw * 0.5) * 2.0;
- return PyFloat_FromDouble(ix == iw ? 1.0 : -1.0);
- }
- /* Else iv != -1.0, and overflow or underflow are possible.
- * Unless we're to write pow() ourselves, we have to trust
- * the platform to do this correctly.
- */
- }
- errno = 0;
- PyFPE_START_PROTECT("pow", return NULL)
- ix = pow(iv, iw);
- PyFPE_END_PROTECT(ix)
- Py_ADJUST_ERANGE1(ix);
- if (errno != 0) {
- /* We don't expect any errno value other than ERANGE, but
- * the range of libm bugs appears unbounded.
- */
- PyErr_SetFromErrno(errno == ERANGE ? PyExc_OverflowError :
- PyExc_ValueError);
- return NULL;
- }
- return PyFloat_FromDouble(ix);
-}
-
-static PyObject *
-float_neg(PyFloatObject *v)
-{
- return PyFloat_FromDouble(-v->ob_fval);
-}
-
-static PyObject *
-float_pos(PyFloatObject *v)
-{
- if (PyFloat_CheckExact(v)) {
- Py_INCREF(v);
- return (PyObject *)v;
- }
- else
- return PyFloat_FromDouble(v->ob_fval);
-}
-
-static PyObject *
-float_abs(PyFloatObject *v)
-{
- return PyFloat_FromDouble(fabs(v->ob_fval));
-}
-
-static int
-float_nonzero(PyFloatObject *v)
-{
- return v->ob_fval != 0.0;
-}
-
-static int
-float_coerce(PyObject **pv, PyObject **pw)
-{
- if (PyInt_Check(*pw)) {
- long x = PyInt_AsLong(*pw);
- *pw = PyFloat_FromDouble((double)x);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyLong_Check(*pw)) {
- double x = PyLong_AsDouble(*pw);
- if (x == -1.0 && PyErr_Occurred())
- return -1;
- *pw = PyFloat_FromDouble(x);
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyFloat_Check(*pw)) {
- Py_INCREF(*pv);
- Py_INCREF(*pw);
- return 0;
- }
- return 1; /* Can't do it */
-}
-
-static PyObject *
-float_long(PyObject *v)
-{
- double x = PyFloat_AsDouble(v);
- return PyLong_FromDouble(x);
-}
-
-static PyObject *
-float_int(PyObject *v)
-{
- double x = PyFloat_AsDouble(v);
- double wholepart; /* integral portion of x, rounded toward 0 */
-
- (void)modf(x, &wholepart);
- /* Try to get out cheap if this fits in a Python int. The attempt
- * to cast to long must be protected, as C doesn't define what
- * happens if the double is too big to fit in a long. Some rare
- * systems raise an exception then (RISCOS was mentioned as one,
- * and someone using a non-default option on Sun also bumped into
- * that). Note that checking for >= and <= LONG_{MIN,MAX} would
- * still be vulnerable: if a long has more bits of precision than
- * a double, casting MIN/MAX to double may yield an approximation,
- * and if that's rounded up, then, e.g., wholepart=LONG_MAX+1 would
- * yield true from the C expression wholepart<=LONG_MAX, despite
- * that wholepart is actually greater than LONG_MAX.
- */
- if (LONG_MIN < wholepart && wholepart < LONG_MAX) {
- const long aslong = (long)wholepart;
- return PyInt_FromLong(aslong);
- }
- return PyLong_FromDouble(wholepart);
-}
-
-static PyObject *
-float_float(PyObject *v)
-{
- if (PyFloat_CheckExact(v))
- Py_INCREF(v);
- else
- v = PyFloat_FromDouble(((PyFloatObject *)v)->ob_fval);
- return v;
-}
-
-
-static PyObject *
-float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyObject *
-float_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *x = Py_False; /* Integer zero */
- static char *kwlist[] = {"x", 0};
-
- if (type != &PyFloat_Type)
- return float_subtype_new(type, args, kwds); /* Wimp out */
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:float", kwlist, &x))
- return NULL;
- if (PyString_Check(x))
- return PyFloat_FromString(x, NULL);
- return PyNumber_Float(x);
-}
-
-/* Wimpy, slow approach to tp_new calls for subtypes of float:
- first create a regular float from whatever arguments we got,
- then allocate a subtype instance and initialize its ob_fval
- from the regular float. The regular float is then thrown away.
-*/
-static PyObject *
-float_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *tmp, *newobj;
-
- assert(PyType_IsSubtype(type, &PyFloat_Type));
- tmp = float_new(&PyFloat_Type, args, kwds);
- if (tmp == NULL)
- return NULL;
- assert(PyFloat_CheckExact(tmp));
- newobj = type->tp_alloc(type, 0);
- if (newobj == NULL) {
- Py_DECREF(tmp);
- return NULL;
- }
- ((PyFloatObject *)newobj)->ob_fval = ((PyFloatObject *)tmp)->ob_fval;
- Py_DECREF(tmp);
- return newobj;
-}
-
-static PyObject *
-float_getnewargs(PyFloatObject *v)
-{
- return Py_BuildValue("(d)", v->ob_fval);
-}
-
-/* this is for the benefit of the pack/unpack routines below */
-
-typedef enum {
- unknown_format, ieee_big_endian_format, ieee_little_endian_format
-} float_format_type;
-
-static float_format_type double_format, float_format;
-static float_format_type detected_double_format, detected_float_format;
-
-static PyObject *
-float_getformat(PyTypeObject *v, PyObject* arg)
-{
- char* s;
- float_format_type r;
-
- if (!PyString_Check(arg)) {
- PyErr_Format(PyExc_TypeError,
- "__getformat__() argument must be string, not %.500s",
- arg->ob_type->tp_name);
- return NULL;
- }
- s = PyString_AS_STRING(arg);
- if (strcmp(s, "double") == 0) {
- r = double_format;
- }
- else if (strcmp(s, "float") == 0) {
- r = float_format;
- }
- else {
- PyErr_SetString(PyExc_ValueError,
- "__getformat__() argument 1 must be "
- "'double' or 'float'");
- return NULL;
- }
-
- switch (r) {
- case unknown_format:
- return PyString_FromString("unknown");
- case ieee_little_endian_format:
- return PyString_FromString("IEEE, little-endian");
- case ieee_big_endian_format:
- return PyString_FromString("IEEE, big-endian");
- default:
- Py_FatalError("insane float_format or double_format");
- return NULL;
- }
-}
-
-PyDoc_STRVAR(float_getformat_doc,
-"float.__getformat__(tstr) -> string\n"
-"\n"
-"You probably don't want to use this function. It exists mainly to be\n"
-"used in Python's test suite.\n"
-"\n"
-"tstr must be 'double' or 'float'. This function returns whichever of\n"
-"'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the\n"
-"format of floating point numbers used by the C type named by tstr.");
-
-static PyObject *
-float_setformat(PyTypeObject *v, PyObject* args)
-{
- char* tstr;
- char* format;
- float_format_type f;
- float_format_type detected;
- float_format_type *p;
-
- if (!PyArg_ParseTuple(args, "ss:__setformat__", &tstr, &format))
- return NULL;
-
- if (strcmp(tstr, "double") == 0) {
- p = &double_format;
- detected = detected_double_format;
- }
- else if (strcmp(tstr, "float") == 0) {
- p = &float_format;
- detected = detected_float_format;
- }
- else {
- PyErr_SetString(PyExc_ValueError,
- "__setformat__() argument 1 must "
- "be 'double' or 'float'");
- return NULL;
- }
-
- if (strcmp(format, "unknown") == 0) {
- f = unknown_format;
- }
- else if (strcmp(format, "IEEE, little-endian") == 0) {
- f = ieee_little_endian_format;
- }
- else if (strcmp(format, "IEEE, big-endian") == 0) {
- f = ieee_big_endian_format;
- }
- else {
- PyErr_SetString(PyExc_ValueError,
- "__setformat__() argument 2 must be "
- "'unknown', 'IEEE, little-endian' or "
- "'IEEE, big-endian'");
- return NULL;
-
- }
-
- if (f != unknown_format && f != detected) {
- PyErr_Format(PyExc_ValueError,
- "can only set %s format to 'unknown' or the "
- "detected platform value", tstr);
- return NULL;
- }
-
- *p = f;
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(float_setformat_doc,
-"float.__setformat__(tstr, fmt) -> None\n"
-"\n"
-"You probably don't want to use this function. It exists mainly to be\n"
-"used in Python's test suite.\n"
-"\n"
-"tstr must be 'double' or 'float'. fmt must be one of 'unknown',\n"
-"'IEEE, big-endian' or 'IEEE, little-endian', and in addition can only be\n"
-"one of the latter two if it appears to match the underlying C reality.\n"
-"\n"
-"Overrides the automatic determination of C-level floating point type.\n"
-"This affects how floats are converted to and from binary strings.");
-
-static PyMethodDef float_methods[] = {
- {"__getnewargs__", (PyCFunction)float_getnewargs, METH_NOARGS},
- {"__getformat__", (PyCFunction)float_getformat,
- METH_O|METH_CLASS, float_getformat_doc},
- {"__setformat__", (PyCFunction)float_setformat,
- METH_VARARGS|METH_CLASS, float_setformat_doc},
- {NULL, NULL} /* sentinel */
-};
-
-PyDoc_STRVAR(float_doc,
-"float(x) -> floating point number\n\
-\n\
-Convert a string or number to a floating point number, if possible.");
-
-
-static PyNumberMethods float_as_number = {
- float_add, /*nb_add*/
- float_sub, /*nb_subtract*/
- float_mul, /*nb_multiply*/
- float_classic_div, /*nb_divide*/
- float_rem, /*nb_remainder*/
- float_divmod, /*nb_divmod*/
- float_pow, /*nb_power*/
- (unaryfunc)float_neg, /*nb_negative*/
- (unaryfunc)float_pos, /*nb_positive*/
- (unaryfunc)float_abs, /*nb_absolute*/
- (inquiry)float_nonzero, /*nb_nonzero*/
- 0, /*nb_invert*/
- 0, /*nb_lshift*/
- 0, /*nb_rshift*/
- 0, /*nb_and*/
- 0, /*nb_xor*/
- 0, /*nb_or*/
- float_coerce, /*nb_coerce*/
- float_int, /*nb_int*/
- float_long, /*nb_long*/
- float_float, /*nb_float*/
- 0, /* nb_oct */
- 0, /* nb_hex */
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_divide */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- float_floor_div, /* nb_floor_divide */
- float_div, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
-};
-
-PyTypeObject PyFloat_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "float",
- sizeof(PyFloatObject),
- 0,
- (destructor)float_dealloc, /* tp_dealloc */
- (printfunc)float_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)float_repr, /* tp_repr */
- &float_as_number, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)float_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)float_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- float_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- float_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- float_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- float_new, /* tp_new */
-};
-
-void
-_PyFloat_Init(void)
-{
- /* We attempt to determine if this machine is using IEEE
- floating point formats by peering at the bits of some
- carefully chosen values. If it looks like we are on an
- IEEE platform, the float packing/unpacking routines can
- just copy bits, if not they resort to arithmetic & shifts
- and masks. The shifts & masks approach works on all finite
- values, but what happens to infinities, NaNs and signed
- zeroes on packing is an accident, and attempting to unpack
- a NaN or an infinity will raise an exception.
-
- Note that if we're on some whacked-out platform which uses
- IEEE formats but isn't strictly little-endian or big-
- endian, we will fall back to the portable shifts & masks
- method. */
-
-#if SIZEOF_DOUBLE == 8
- {
- double x = 9006104071832581.0;
- if (memcmp(&x, "\x43\x3f\xff\x01\x02\x03\x04\x05", 8) == 0)
- detected_double_format = ieee_big_endian_format;
- else if (memcmp(&x, "\x05\x04\x03\x02\x01\xff\x3f\x43", 8) == 0)
- detected_double_format = ieee_little_endian_format;
- else
- detected_double_format = unknown_format;
- }
-#else
- detected_double_format = unknown_format;
-#endif
-
-#if SIZEOF_FLOAT == 4
- {
- float y = 16711938.0;
- if (memcmp(&y, "\x4b\x7f\x01\x02", 4) == 0)
- detected_float_format = ieee_big_endian_format;
- else if (memcmp(&y, "\x02\x01\x7f\x4b", 4) == 0)
- detected_float_format = ieee_little_endian_format;
- else
- detected_float_format = unknown_format;
- }
-#else
- detected_float_format = unknown_format;
-#endif
-
- double_format = detected_double_format;
- float_format = detected_float_format;
-}
-
-void
-PyFloat_Fini(void)
-{
- PyFloatObject *p;
- PyFloatBlock *list, *next;
- unsigned i;
- int bc, bf; /* block count, number of freed blocks */
- int frem, fsum; /* remaining unfreed floats per block, total */
-
- bc = 0;
- bf = 0;
- fsum = 0;
- list = block_list;
- block_list = NULL;
- free_list = NULL;
- while (list != NULL) {
- bc++;
- frem = 0;
- for (i = 0, p = &list->objects[0];
- i < N_FLOATOBJECTS;
- i++, p++) {
- if (PyFloat_CheckExact(p) && p->ob_refcnt != 0)
- frem++;
- }
- next = list->next;
- if (frem) {
- list->next = block_list;
- block_list = list;
- for (i = 0, p = &list->objects[0];
- i < N_FLOATOBJECTS;
- i++, p++) {
- if (!PyFloat_CheckExact(p) ||
- p->ob_refcnt == 0) {
- p->ob_type = (struct _typeobject *)
- free_list;
- free_list = p;
- }
- }
- }
- else {
- PyMem_FREE(list); /* XXX PyObject_FREE ??? */
- bf++;
- }
- fsum += frem;
- list = next;
- }
- if (!Py_VerboseFlag)
- return;
- fprintf(stderr, "# cleanup floats");
- if (!fsum) {
- fprintf(stderr, "\n");
- }
- else {
- fprintf(stderr,
- ": %d unfreed float%s in %d out of %d block%s\n",
- fsum, fsum == 1 ? "" : "s",
- bc - bf, bc, bc == 1 ? "" : "s");
- }
- if (Py_VerboseFlag > 1) {
- list = block_list;
- while (list != NULL) {
- for (i = 0, p = &list->objects[0];
- i < N_FLOATOBJECTS;
- i++, p++) {
- if (PyFloat_CheckExact(p) &&
- p->ob_refcnt != 0) {
- char buf[100];
- PyFloat_AsString(buf, p);
- /* XXX(twouters) cast refcount to
- long until %zd is universally
- available
- */
- fprintf(stderr,
- "# <float at %p, refcnt=%ld, val=%s>\n",
- p, (long)p->ob_refcnt, buf);
- }
- }
- list = list->next;
- }
- }
-}
-
-/*----------------------------------------------------------------------------
- * _PyFloat_{Pack,Unpack}{4,8}. See floatobject.h.
- *
- * TODO: On platforms that use the standard IEEE-754 single and double
- * formats natively, these routines could simply copy the bytes.
- */
-int
-_PyFloat_Pack4(double x, unsigned char *p, int le)
-{
- if (float_format == unknown_format) {
- unsigned char sign;
- int e;
- double f;
- unsigned int fbits;
- int incr = 1;
-
- if (le) {
- p += 3;
- incr = -1;
- }
-
- if (x < 0) {
- sign = 1;
- x = -x;
- }
- else
- sign = 0;
-
- f = frexp(x, &e);
-
- /* Normalize f to be in the range [1.0, 2.0) */
- if (0.5 <= f && f < 1.0) {
- f *= 2.0;
- e--;
- }
- else if (f == 0.0)
- e = 0;
- else {
- PyErr_SetString(PyExc_SystemError,
- "frexp() result out of range");
- return -1;
- }
-
- if (e >= 128)
- goto Overflow;
- else if (e < -126) {
- /* Gradual underflow */
- f = ldexp(f, 126 + e);
- e = 0;
- }
- else if (!(e == 0 && f == 0.0)) {
- e += 127;
- f -= 1.0; /* Get rid of leading 1 */
- }
-
- f *= 8388608.0; /* 2**23 */
- fbits = (unsigned int)(f + 0.5); /* Round */
- assert(fbits <= 8388608);
- if (fbits >> 23) {
- /* The carry propagated out of a string of 23 1 bits. */
- fbits = 0;
- ++e;
- if (e >= 255)
- goto Overflow;
- }
-
- /* First byte */
- *p = (sign << 7) | (e >> 1);
- p += incr;
-
- /* Second byte */
- *p = (char) (((e & 1) << 7) | (fbits >> 16));
- p += incr;
-
- /* Third byte */
- *p = (fbits >> 8) & 0xFF;
- p += incr;
-
- /* Fourth byte */
- *p = fbits & 0xFF;
-
- /* Done */
- return 0;
-
- Overflow:
- PyErr_SetString(PyExc_OverflowError,
- "float too large to pack with f format");
- return -1;
- }
- else {
- float y = (float)x;
- const char *s = (char*)&y;
- int i, incr = 1;
-
- if ((float_format == ieee_little_endian_format && !le)
- || (float_format == ieee_big_endian_format && le)) {
- p += 3;
- incr = -1;
- }
-
- for (i = 0; i < 4; i++) {
- *p = *s++;
- p += incr;
- }
- return 0;
- }
-}
-
-int
-_PyFloat_Pack8(double x, unsigned char *p, int le)
-{
- if (double_format == unknown_format) {
- unsigned char sign;
- int e;
- double f;
- unsigned int fhi, flo;
- int incr = 1;
-
- if (le) {
- p += 7;
- incr = -1;
- }
-
- if (x < 0) {
- sign = 1;
- x = -x;
- }
- else
- sign = 0;
-
- f = frexp(x, &e);
-
- /* Normalize f to be in the range [1.0, 2.0) */
- if (0.5 <= f && f < 1.0) {
- f *= 2.0;
- e--;
- }
- else if (f == 0.0)
- e = 0;
- else {
- PyErr_SetString(PyExc_SystemError,
- "frexp() result out of range");
- return -1;
- }
-
- if (e >= 1024)
- goto Overflow;
- else if (e < -1022) {
- /* Gradual underflow */
- f = ldexp(f, 1022 + e);
- e = 0;
- }
- else if (!(e == 0 && f == 0.0)) {
- e += 1023;
- f -= 1.0; /* Get rid of leading 1 */
- }
-
- /* fhi receives the high 28 bits; flo the low 24 bits (== 52 bits) */
- f *= 268435456.0; /* 2**28 */
- fhi = (unsigned int)f; /* Truncate */
- assert(fhi < 268435456);
-
- f -= (double)fhi;
- f *= 16777216.0; /* 2**24 */
- flo = (unsigned int)(f + 0.5); /* Round */
- assert(flo <= 16777216);
- if (flo >> 24) {
- /* The carry propagated out of a string of 24 1 bits. */
- flo = 0;
- ++fhi;
- if (fhi >> 28) {
- /* And it also progagated out of the next 28 bits. */
- fhi = 0;
- ++e;
- if (e >= 2047)
- goto Overflow;
- }
- }
-
- /* First byte */
- *p = (sign << 7) | (e >> 4);
- p += incr;
-
- /* Second byte */
- *p = (unsigned char) (((e & 0xF) << 4) | (fhi >> 24));
- p += incr;
-
- /* Third byte */
- *p = (fhi >> 16) & 0xFF;
- p += incr;
-
- /* Fourth byte */
- *p = (fhi >> 8) & 0xFF;
- p += incr;
-
- /* Fifth byte */
- *p = fhi & 0xFF;
- p += incr;
-
- /* Sixth byte */
- *p = (flo >> 16) & 0xFF;
- p += incr;
-
- /* Seventh byte */
- *p = (flo >> 8) & 0xFF;
- p += incr;
-
- /* Eighth byte */
- *p = flo & 0xFF;
- p += incr;
-
- /* Done */
- return 0;
-
- Overflow:
- PyErr_SetString(PyExc_OverflowError,
- "float too large to pack with d format");
- return -1;
- }
- else {
- const char *s = (char*)&x;
- int i, incr = 1;
-
- if ((double_format == ieee_little_endian_format && !le)
- || (double_format == ieee_big_endian_format && le)) {
- p += 7;
- incr = -1;
- }
-
- for (i = 0; i < 8; i++) {
- *p = *s++;
- p += incr;
- }
- return 0;
- }
-}
-
-double
-_PyFloat_Unpack4(const unsigned char *p, int le)
-{
- if (float_format == unknown_format) {
- unsigned char sign;
- int e;
- unsigned int f;
- double x;
- int incr = 1;
-
- if (le) {
- p += 3;
- incr = -1;
- }
-
- /* First byte */
- sign = (*p >> 7) & 1;
- e = (*p & 0x7F) << 1;
- p += incr;
-
- /* Second byte */
- e |= (*p >> 7) & 1;
- f = (*p & 0x7F) << 16;
- p += incr;
-
- if (e == 255) {
- PyErr_SetString(
- PyExc_ValueError,
- "can't unpack IEEE 754 special value "
- "on non-IEEE platform");
- return -1;
- }
-
- /* Third byte */
- f |= *p << 8;
- p += incr;
-
- /* Fourth byte */
- f |= *p;
-
- x = (double)f / 8388608.0;
-
- /* XXX This sadly ignores Inf/NaN issues */
- if (e == 0)
- e = -126;
- else {
- x += 1.0;
- e -= 127;
- }
- x = ldexp(x, e);
-
- if (sign)
- x = -x;
-
- return x;
- }
- else {
- float x;
-
- if ((float_format == ieee_little_endian_format && !le)
- || (float_format == ieee_big_endian_format && le)) {
- char buf[4];
- char *d = &buf[3];
- int i;
-
- for (i = 0; i < 4; i++) {
- *d-- = *p++;
- }
- memcpy(&x, buf, 4);
- }
- else {
- memcpy(&x, p, 4);
- }
-
- return x;
- }
-}
-
-double
-_PyFloat_Unpack8(const unsigned char *p, int le)
-{
- if (double_format == unknown_format) {
- unsigned char sign;
- int e;
- unsigned int fhi, flo;
- double x;
- int incr = 1;
-
- if (le) {
- p += 7;
- incr = -1;
- }
-
- /* First byte */
- sign = (*p >> 7) & 1;
- e = (*p & 0x7F) << 4;
-
- p += incr;
-
- /* Second byte */
- e |= (*p >> 4) & 0xF;
- fhi = (*p & 0xF) << 24;
- p += incr;
-
- if (e == 2047) {
- PyErr_SetString(
- PyExc_ValueError,
- "can't unpack IEEE 754 special value "
- "on non-IEEE platform");
- return -1.0;
- }
-
- /* Third byte */
- fhi |= *p << 16;
- p += incr;
-
- /* Fourth byte */
- fhi |= *p << 8;
- p += incr;
-
- /* Fifth byte */
- fhi |= *p;
- p += incr;
-
- /* Sixth byte */
- flo = *p << 16;
- p += incr;
-
- /* Seventh byte */
- flo |= *p << 8;
- p += incr;
-
- /* Eighth byte */
- flo |= *p;
-
- x = (double)fhi + (double)flo / 16777216.0; /* 2**24 */
- x /= 268435456.0; /* 2**28 */
-
- if (e == 0)
- e = -1022;
- else {
- x += 1.0;
- e -= 1023;
- }
- x = ldexp(x, e);
-
- if (sign)
- x = -x;
-
- return x;
- }
- else {
- double x;
-
- if ((double_format == ieee_little_endian_format && !le)
- || (double_format == ieee_big_endian_format && le)) {
- char buf[8];
- char *d = &buf[7];
- int i;
-
- for (i = 0; i < 8; i++) {
- *d-- = *p++;
- }
- memcpy(&x, buf, 8);
- }
- else {
- memcpy(&x, p, 8);
- }
-
- return x;
- }
-}
diff --git a/sys/src/cmd/python/Objects/frameobject.c b/sys/src/cmd/python/Objects/frameobject.c
deleted file mode 100644
index 3a073b6fa..000000000
--- a/sys/src/cmd/python/Objects/frameobject.c
+++ /dev/null
@@ -1,849 +0,0 @@
-/* Frame object implementation */
-
-#include "Python.h"
-
-#include "code.h"
-#include "frameobject.h"
-#include "opcode.h"
-#include "structmember.h"
-
-#undef MIN
-#undef MAX
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
-#define OFF(x) offsetof(PyFrameObject, x)
-
-static PyMemberDef frame_memberlist[] = {
- {"f_back", T_OBJECT, OFF(f_back), RO},
- {"f_code", T_OBJECT, OFF(f_code), RO},
- {"f_builtins", T_OBJECT, OFF(f_builtins),RO},
- {"f_globals", T_OBJECT, OFF(f_globals), RO},
- {"f_lasti", T_INT, OFF(f_lasti), RO},
- {"f_exc_type", T_OBJECT, OFF(f_exc_type)},
- {"f_exc_value", T_OBJECT, OFF(f_exc_value)},
- {"f_exc_traceback", T_OBJECT, OFF(f_exc_traceback)},
- {NULL} /* Sentinel */
-};
-
-static PyObject *
-frame_getlocals(PyFrameObject *f, void *closure)
-{
- PyFrame_FastToLocals(f);
- Py_INCREF(f->f_locals);
- return f->f_locals;
-}
-
-static PyObject *
-frame_getlineno(PyFrameObject *f, void *closure)
-{
- int lineno;
-
- if (f->f_trace)
- lineno = f->f_lineno;
- else
- lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
-
- return PyInt_FromLong(lineno);
-}
-
-/* Setter for f_lineno - you can set f_lineno from within a trace function in
- * order to jump to a given line of code, subject to some restrictions. Most
- * lines are OK to jump to because they don't make any assumptions about the
- * state of the stack (obvious because you could remove the line and the code
- * would still work without any stack errors), but there are some constructs
- * that limit jumping:
- *
- * o Lines with an 'except' statement on them can't be jumped to, because
- * they expect an exception to be on the top of the stack.
- * o Lines that live in a 'finally' block can't be jumped from or to, since
- * the END_FINALLY expects to clean up the stack after the 'try' block.
- * o 'try'/'for'/'while' blocks can't be jumped into because the blockstack
- * needs to be set up before their code runs, and for 'for' loops the
- * iterator needs to be on the stack.
- */
-static int
-frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno)
-{
- int new_lineno = 0; /* The new value of f_lineno */
- int new_lasti = 0; /* The new value of f_lasti */
- int new_iblock = 0; /* The new value of f_iblock */
- char *code = NULL; /* The bytecode for the frame... */
- Py_ssize_t code_len = 0; /* ...and its length */
- char *lnotab = NULL; /* Iterating over co_lnotab */
- Py_ssize_t lnotab_len = 0; /* (ditto) */
- int offset = 0; /* (ditto) */
- int line = 0; /* (ditto) */
- int addr = 0; /* (ditto) */
- int min_addr = 0; /* Scanning the SETUPs and POPs */
- int max_addr = 0; /* (ditto) */
- int delta_iblock = 0; /* (ditto) */
- int min_delta_iblock = 0; /* (ditto) */
- int min_iblock = 0; /* (ditto) */
- int f_lasti_setup_addr = 0; /* Policing no-jump-into-finally */
- int new_lasti_setup_addr = 0; /* (ditto) */
- int blockstack[CO_MAXBLOCKS]; /* Walking the 'finally' blocks */
- int in_finally[CO_MAXBLOCKS]; /* (ditto) */
- int blockstack_top = 0; /* (ditto) */
- int setup_op = 0; /* (ditto) */
-
- /* f_lineno must be an integer. */
- if (!PyInt_Check(p_new_lineno)) {
- PyErr_SetString(PyExc_ValueError,
- "lineno must be an integer");
- return -1;
- }
-
- /* You can only do this from within a trace function, not via
- * _getframe or similar hackery. */
- if (!f->f_trace)
- {
- PyErr_Format(PyExc_ValueError,
- "f_lineno can only be set by a trace function");
- return -1;
- }
-
- /* Fail if the line comes before the start of the code block. */
- new_lineno = (int) PyInt_AsLong(p_new_lineno);
- if (new_lineno < f->f_code->co_firstlineno) {
- PyErr_Format(PyExc_ValueError,
- "line %d comes before the current code block",
- new_lineno);
- return -1;
- }
-
- /* Find the bytecode offset for the start of the given line, or the
- * first code-owning line after it. */
- PyString_AsStringAndSize(f->f_code->co_lnotab, &lnotab, &lnotab_len);
- addr = 0;
- line = f->f_code->co_firstlineno;
- new_lasti = -1;
- for (offset = 0; offset < lnotab_len; offset += 2) {
- addr += lnotab[offset];
- line += lnotab[offset+1];
- if (line >= new_lineno) {
- new_lasti = addr;
- new_lineno = line;
- break;
- }
- }
-
- /* If we didn't reach the requested line, return an error. */
- if (new_lasti == -1) {
- PyErr_Format(PyExc_ValueError,
- "line %d comes after the current code block",
- new_lineno);
- return -1;
- }
-
- /* We're now ready to look at the bytecode. */
- PyString_AsStringAndSize(f->f_code->co_code, &code, &code_len);
- min_addr = MIN(new_lasti, f->f_lasti);
- max_addr = MAX(new_lasti, f->f_lasti);
-
- /* You can't jump onto a line with an 'except' statement on it -
- * they expect to have an exception on the top of the stack, which
- * won't be true if you jump to them. They always start with code
- * that either pops the exception using POP_TOP (plain 'except:'
- * lines do this) or duplicates the exception on the stack using
- * DUP_TOP (if there's an exception type specified). See compile.c,
- * 'com_try_except' for the full details. There aren't any other
- * cases (AFAIK) where a line's code can start with DUP_TOP or
- * POP_TOP, but if any ever appear, they'll be subject to the same
- * restriction (but with a different error message). */
- if (code[new_lasti] == DUP_TOP || code[new_lasti] == POP_TOP) {
- PyErr_SetString(PyExc_ValueError,
- "can't jump to 'except' line as there's no exception");
- return -1;
- }
-
- /* You can't jump into or out of a 'finally' block because the 'try'
- * block leaves something on the stack for the END_FINALLY to clean
- * up. So we walk the bytecode, maintaining a simulated blockstack.
- * When we reach the old or new address and it's in a 'finally' block
- * we note the address of the corresponding SETUP_FINALLY. The jump
- * is only legal if neither address is in a 'finally' block or
- * they're both in the same one. 'blockstack' is a stack of the
- * bytecode addresses of the SETUP_X opcodes, and 'in_finally' tracks
- * whether we're in a 'finally' block at each blockstack level. */
- f_lasti_setup_addr = -1;
- new_lasti_setup_addr = -1;
- memset(blockstack, '\0', sizeof(blockstack));
- memset(in_finally, '\0', sizeof(in_finally));
- blockstack_top = 0;
- for (addr = 0; addr < code_len; addr++) {
- unsigned char op = code[addr];
- switch (op) {
- case SETUP_LOOP:
- case SETUP_EXCEPT:
- case SETUP_FINALLY:
- blockstack[blockstack_top++] = addr;
- in_finally[blockstack_top-1] = 0;
- break;
-
- case POP_BLOCK:
- assert(blockstack_top > 0);
- setup_op = code[blockstack[blockstack_top-1]];
- if (setup_op == SETUP_FINALLY) {
- in_finally[blockstack_top-1] = 1;
- }
- else {
- blockstack_top--;
- }
- break;
-
- case END_FINALLY:
- /* Ignore END_FINALLYs for SETUP_EXCEPTs - they exist
- * in the bytecode but don't correspond to an actual
- * 'finally' block. (If blockstack_top is 0, we must
- * be seeing such an END_FINALLY.) */
- if (blockstack_top > 0) {
- setup_op = code[blockstack[blockstack_top-1]];
- if (setup_op == SETUP_FINALLY) {
- blockstack_top--;
- }
- }
- break;
- }
-
- /* For the addresses we're interested in, see whether they're
- * within a 'finally' block and if so, remember the address
- * of the SETUP_FINALLY. */
- if (addr == new_lasti || addr == f->f_lasti) {
- int i = 0;
- int setup_addr = -1;
- for (i = blockstack_top-1; i >= 0; i--) {
- if (in_finally[i]) {
- setup_addr = blockstack[i];
- break;
- }
- }
-
- if (setup_addr != -1) {
- if (addr == new_lasti) {
- new_lasti_setup_addr = setup_addr;
- }
-
- if (addr == f->f_lasti) {
- f_lasti_setup_addr = setup_addr;
- }
- }
- }
-
- if (op >= HAVE_ARGUMENT) {
- addr += 2;
- }
- }
-
- /* Verify that the blockstack tracking code didn't get lost. */
- assert(blockstack_top == 0);
-
- /* After all that, are we jumping into / out of a 'finally' block? */
- if (new_lasti_setup_addr != f_lasti_setup_addr) {
- PyErr_SetString(PyExc_ValueError,
- "can't jump into or out of a 'finally' block");
- return -1;
- }
-
-
- /* Police block-jumping (you can't jump into the middle of a block)
- * and ensure that the blockstack finishes up in a sensible state (by
- * popping any blocks we're jumping out of). We look at all the
- * blockstack operations between the current position and the new
- * one, and keep track of how many blocks we drop out of on the way.
- * By also keeping track of the lowest blockstack position we see, we
- * can tell whether the jump goes into any blocks without coming out
- * again - in that case we raise an exception below. */
- delta_iblock = 0;
- for (addr = min_addr; addr < max_addr; addr++) {
- unsigned char op = code[addr];
- switch (op) {
- case SETUP_LOOP:
- case SETUP_EXCEPT:
- case SETUP_FINALLY:
- delta_iblock++;
- break;
-
- case POP_BLOCK:
- delta_iblock--;
- break;
- }
-
- min_delta_iblock = MIN(min_delta_iblock, delta_iblock);
-
- if (op >= HAVE_ARGUMENT) {
- addr += 2;
- }
- }
-
- /* Derive the absolute iblock values from the deltas. */
- min_iblock = f->f_iblock + min_delta_iblock;
- if (new_lasti > f->f_lasti) {
- /* Forwards jump. */
- new_iblock = f->f_iblock + delta_iblock;
- }
- else {
- /* Backwards jump. */
- new_iblock = f->f_iblock - delta_iblock;
- }
-
- /* Are we jumping into a block? */
- if (new_iblock > min_iblock) {
- PyErr_SetString(PyExc_ValueError,
- "can't jump into the middle of a block");
- return -1;
- }
-
- /* Pop any blocks that we're jumping out of. */
- while (f->f_iblock > new_iblock) {
- PyTryBlock *b = &f->f_blockstack[--f->f_iblock];
- while ((f->f_stacktop - f->f_valuestack) > b->b_level) {
- PyObject *v = (*--f->f_stacktop);
- Py_DECREF(v);
- }
- }
-
- /* Finally set the new f_lineno and f_lasti and return OK. */
- f->f_lineno = new_lineno;
- f->f_lasti = new_lasti;
- return 0;
-}
-
-static PyObject *
-frame_gettrace(PyFrameObject *f, void *closure)
-{
- PyObject* trace = f->f_trace;
-
- if (trace == NULL)
- trace = Py_None;
-
- Py_INCREF(trace);
-
- return trace;
-}
-
-static int
-frame_settrace(PyFrameObject *f, PyObject* v, void *closure)
-{
- /* We rely on f_lineno being accurate when f_trace is set. */
-
- PyObject* old_value = f->f_trace;
-
- Py_XINCREF(v);
- f->f_trace = v;
-
- if (v != NULL)
- f->f_lineno = PyCode_Addr2Line(f->f_code, f->f_lasti);
-
- Py_XDECREF(old_value);
-
- return 0;
-}
-
-static PyObject *
-frame_getrestricted(PyFrameObject *f, void *closure)
-{
- return PyBool_FromLong(PyFrame_IsRestricted(f));
-}
-
-static PyGetSetDef frame_getsetlist[] = {
- {"f_locals", (getter)frame_getlocals, NULL, NULL},
- {"f_lineno", (getter)frame_getlineno,
- (setter)frame_setlineno, NULL},
- {"f_trace", (getter)frame_gettrace, (setter)frame_settrace, NULL},
- {"f_restricted",(getter)frame_getrestricted,NULL, NULL},
- {0}
-};
-
-/* Stack frames are allocated and deallocated at a considerable rate.
- In an attempt to improve the speed of function calls, we:
-
- 1. Hold a single "zombie" frame on each code object. This retains
- the allocated and initialised frame object from an invocation of
- the code object. The zombie is reanimated the next time we need a
- frame object for that code object. Doing this saves the malloc/
- realloc required when using a free_list frame that isn't the
- correct size. It also saves some field initialisation.
-
- In zombie mode, no field of PyFrameObject holds a reference, but
- the following fields are still valid:
-
- * ob_type, ob_size, f_code, f_valuestack;
-
- * f_locals, f_trace,
- f_exc_type, f_exc_value, f_exc_traceback are NULL;
-
- * f_localsplus does not require re-allocation and
- the local variables in f_localsplus are NULL.
-
- 2. We also maintain a separate free list of stack frames (just like
- integers are allocated in a special way -- see intobject.c). When
- a stack frame is on the free list, only the following members have
- a meaning:
- ob_type == &Frametype
- f_back next item on free list, or NULL
- f_stacksize size of value stack
- ob_size size of localsplus
- Note that the value and block stacks are preserved -- this can save
- another malloc() call or two (and two free() calls as well!).
- Also note that, unlike for integers, each frame object is a
- malloc'ed object in its own right -- it is only the actual calls to
- malloc() that we are trying to save here, not the administration.
- After all, while a typical program may make millions of calls, a
- call depth of more than 20 or 30 is probably already exceptional
- unless the program contains run-away recursion. I hope.
-
- Later, MAXFREELIST was added to bound the # of frames saved on
- free_list. Else programs creating lots of cyclic trash involving
- frames could provoke free_list into growing without bound.
-*/
-
-static PyFrameObject *free_list = NULL;
-static int numfree = 0; /* number of frames currently in free_list */
-#define MAXFREELIST 200 /* max value for numfree */
-
-static void
-frame_dealloc(PyFrameObject *f)
-{
- PyObject **p, **valuestack;
- PyCodeObject *co;
-
- PyObject_GC_UnTrack(f);
- Py_TRASHCAN_SAFE_BEGIN(f)
- /* Kill all local variables */
- valuestack = f->f_valuestack;
- for (p = f->f_localsplus; p < valuestack; p++)
- Py_CLEAR(*p);
-
- /* Free stack */
- if (f->f_stacktop != NULL) {
- for (p = valuestack; p < f->f_stacktop; p++)
- Py_XDECREF(*p);
- }
-
- Py_XDECREF(f->f_back);
- Py_DECREF(f->f_builtins);
- Py_DECREF(f->f_globals);
- Py_CLEAR(f->f_locals);
- Py_CLEAR(f->f_trace);
- Py_CLEAR(f->f_exc_type);
- Py_CLEAR(f->f_exc_value);
- Py_CLEAR(f->f_exc_traceback);
-
- co = f->f_code;
- if (co->co_zombieframe == NULL)
- co->co_zombieframe = f;
- else if (numfree < MAXFREELIST) {
- ++numfree;
- f->f_back = free_list;
- free_list = f;
- }
- else
- PyObject_GC_Del(f);
-
- Py_DECREF(co);
- Py_TRASHCAN_SAFE_END(f)
-}
-
-static int
-frame_traverse(PyFrameObject *f, visitproc visit, void *arg)
-{
- PyObject **fastlocals, **p;
- int i, slots;
-
- Py_VISIT(f->f_back);
- Py_VISIT(f->f_code);
- Py_VISIT(f->f_builtins);
- Py_VISIT(f->f_globals);
- Py_VISIT(f->f_locals);
- Py_VISIT(f->f_trace);
- Py_VISIT(f->f_exc_type);
- Py_VISIT(f->f_exc_value);
- Py_VISIT(f->f_exc_traceback);
-
- /* locals */
- slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
- fastlocals = f->f_localsplus;
- for (i = slots; --i >= 0; ++fastlocals)
- Py_VISIT(*fastlocals);
-
- /* stack */
- if (f->f_stacktop != NULL) {
- for (p = f->f_valuestack; p < f->f_stacktop; p++)
- Py_VISIT(*p);
- }
- return 0;
-}
-
-static void
-frame_clear(PyFrameObject *f)
-{
- PyObject **fastlocals, **p, **oldtop;
- int i, slots;
-
- /* Before anything else, make sure that this frame is clearly marked
- * as being defunct! Else, e.g., a generator reachable from this
- * frame may also point to this frame, believe itself to still be
- * active, and try cleaning up this frame again.
- */
- oldtop = f->f_stacktop;
- f->f_stacktop = NULL;
-
- Py_CLEAR(f->f_exc_type);
- Py_CLEAR(f->f_exc_value);
- Py_CLEAR(f->f_exc_traceback);
- Py_CLEAR(f->f_trace);
-
- /* locals */
- slots = f->f_code->co_nlocals + PyTuple_GET_SIZE(f->f_code->co_cellvars) + PyTuple_GET_SIZE(f->f_code->co_freevars);
- fastlocals = f->f_localsplus;
- for (i = slots; --i >= 0; ++fastlocals)
- Py_CLEAR(*fastlocals);
-
- /* stack */
- if (oldtop != NULL) {
- for (p = f->f_valuestack; p < oldtop; p++)
- Py_CLEAR(*p);
- }
-}
-
-
-PyTypeObject PyFrame_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "frame",
- sizeof(PyFrameObject),
- sizeof(PyObject *),
- (destructor)frame_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)frame_traverse, /* tp_traverse */
- (inquiry)frame_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- frame_memberlist, /* tp_members */
- frame_getsetlist, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
-};
-
-static PyObject *builtin_object;
-
-int _PyFrame_Init()
-{
- builtin_object = PyString_InternFromString("__builtins__");
- return (builtin_object != NULL);
-}
-
-PyFrameObject *
-PyFrame_New(PyThreadState *tstate, PyCodeObject *code, PyObject *globals,
- PyObject *locals)
-{
- PyFrameObject *back = tstate->frame;
- PyFrameObject *f;
- PyObject *builtins;
- Py_ssize_t i;
-
-#ifdef Py_DEBUG
- if (code == NULL || globals == NULL || !PyDict_Check(globals) ||
- (locals != NULL && !PyMapping_Check(locals))) {
- PyErr_BadInternalCall();
- return NULL;
- }
-#endif
- if (back == NULL || back->f_globals != globals) {
- builtins = PyDict_GetItem(globals, builtin_object);
- if (builtins) {
- if (PyModule_Check(builtins)) {
- builtins = PyModule_GetDict(builtins);
- assert(!builtins || PyDict_Check(builtins));
- }
- else if (!PyDict_Check(builtins))
- builtins = NULL;
- }
- if (builtins == NULL) {
- /* No builtins! Make up a minimal one
- Give them 'None', at least. */
- builtins = PyDict_New();
- if (builtins == NULL ||
- PyDict_SetItemString(
- builtins, "None", Py_None) < 0)
- return NULL;
- }
- else
- Py_INCREF(builtins);
-
- }
- else {
- /* If we share the globals, we share the builtins.
- Save a lookup and a call. */
- builtins = back->f_builtins;
- assert(builtins != NULL && PyDict_Check(builtins));
- Py_INCREF(builtins);
- }
- if (code->co_zombieframe != NULL) {
- f = code->co_zombieframe;
- code->co_zombieframe = NULL;
- _Py_NewReference((PyObject *)f);
- assert(f->f_code == code);
- }
- else {
- Py_ssize_t extras, ncells, nfrees;
- ncells = PyTuple_GET_SIZE(code->co_cellvars);
- nfrees = PyTuple_GET_SIZE(code->co_freevars);
- extras = code->co_stacksize + code->co_nlocals + ncells +
- nfrees;
- if (free_list == NULL) {
- f = PyObject_GC_NewVar(PyFrameObject, &PyFrame_Type,
- extras);
- if (f == NULL) {
- Py_DECREF(builtins);
- return NULL;
- }
- }
- else {
- assert(numfree > 0);
- --numfree;
- f = free_list;
- free_list = free_list->f_back;
- if (f->ob_size < extras) {
- f = PyObject_GC_Resize(PyFrameObject, f, extras);
- if (f == NULL) {
- Py_DECREF(builtins);
- return NULL;
- }
- }
- _Py_NewReference((PyObject *)f);
- }
-
- f->f_code = code;
- extras = code->co_nlocals + ncells + nfrees;
- f->f_valuestack = f->f_localsplus + extras;
- for (i=0; i<extras; i++)
- f->f_localsplus[i] = NULL;
- f->f_locals = NULL;
- f->f_trace = NULL;
- f->f_exc_type = f->f_exc_value = f->f_exc_traceback = NULL;
- }
- f->f_stacktop = f->f_valuestack;
- f->f_builtins = builtins;
- Py_XINCREF(back);
- f->f_back = back;
- Py_INCREF(code);
- Py_INCREF(globals);
- f->f_globals = globals;
- /* Most functions have CO_NEWLOCALS and CO_OPTIMIZED set. */
- if ((code->co_flags & (CO_NEWLOCALS | CO_OPTIMIZED)) ==
- (CO_NEWLOCALS | CO_OPTIMIZED))
- ; /* f_locals = NULL; will be set by PyFrame_FastToLocals() */
- else if (code->co_flags & CO_NEWLOCALS) {
- locals = PyDict_New();
- if (locals == NULL) {
- Py_DECREF(f);
- return NULL;
- }
- f->f_locals = locals;
- }
- else {
- if (locals == NULL)
- locals = globals;
- Py_INCREF(locals);
- f->f_locals = locals;
- }
- f->f_tstate = tstate;
-
- f->f_lasti = -1;
- f->f_lineno = code->co_firstlineno;
- f->f_iblock = 0;
-
- _PyObject_GC_TRACK(f);
- return f;
-}
-
-/* Block management */
-
-void
-PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level)
-{
- PyTryBlock *b;
- if (f->f_iblock >= CO_MAXBLOCKS)
- Py_FatalError("XXX block stack overflow");
- b = &f->f_blockstack[f->f_iblock++];
- b->b_type = type;
- b->b_level = level;
- b->b_handler = handler;
-}
-
-PyTryBlock *
-PyFrame_BlockPop(PyFrameObject *f)
-{
- PyTryBlock *b;
- if (f->f_iblock <= 0)
- Py_FatalError("XXX block stack underflow");
- b = &f->f_blockstack[--f->f_iblock];
- return b;
-}
-
-/* Convert between "fast" version of locals and dictionary version */
-
-static void
-map_to_dict(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
- Py_ssize_t deref)
-{
- Py_ssize_t j;
- for (j = nmap; --j >= 0; ) {
- PyObject *key = PyTuple_GET_ITEM(map, j);
- PyObject *value = values[j];
- if (deref)
- value = PyCell_GET(value);
- if (value == NULL) {
- if (PyObject_DelItem(dict, key) != 0)
- PyErr_Clear();
- }
- else {
- if (PyObject_SetItem(dict, key, value) != 0)
- PyErr_Clear();
- }
- }
-}
-
-static void
-dict_to_map(PyObject *map, Py_ssize_t nmap, PyObject *dict, PyObject **values,
- Py_ssize_t deref, int clear)
-{
- Py_ssize_t j;
- for (j = nmap; --j >= 0; ) {
- PyObject *key = PyTuple_GET_ITEM(map, j);
- PyObject *value = PyObject_GetItem(dict, key);
- if (value == NULL)
- PyErr_Clear();
- if (deref) {
- if (value || clear) {
- if (PyCell_GET(values[j]) != value) {
- if (PyCell_Set(values[j], value) < 0)
- PyErr_Clear();
- }
- }
- } else if (value != NULL || clear) {
- if (values[j] != value) {
- Py_XINCREF(value);
- Py_XDECREF(values[j]);
- values[j] = value;
- }
- }
- Py_XDECREF(value);
- }
-}
-
-void
-PyFrame_FastToLocals(PyFrameObject *f)
-{
- /* Merge fast locals into f->f_locals */
- PyObject *locals, *map;
- PyObject **fast;
- PyObject *error_type, *error_value, *error_traceback;
- PyCodeObject *co;
- Py_ssize_t j;
- int ncells, nfreevars;
- if (f == NULL)
- return;
- locals = f->f_locals;
- if (locals == NULL) {
- locals = f->f_locals = PyDict_New();
- if (locals == NULL) {
- PyErr_Clear(); /* Can't report it :-( */
- return;
- }
- }
- co = f->f_code;
- map = co->co_varnames;
- if (!PyTuple_Check(map))
- return;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
- fast = f->f_localsplus;
- j = PyTuple_GET_SIZE(map);
- if (j > co->co_nlocals)
- j = co->co_nlocals;
- if (co->co_nlocals)
- map_to_dict(map, j, locals, fast, 0);
- ncells = PyTuple_GET_SIZE(co->co_cellvars);
- nfreevars = PyTuple_GET_SIZE(co->co_freevars);
- if (ncells || nfreevars) {
- map_to_dict(co->co_cellvars, ncells,
- locals, fast + co->co_nlocals, 1);
- map_to_dict(co->co_freevars, nfreevars,
- locals, fast + co->co_nlocals + ncells, 1);
- }
- PyErr_Restore(error_type, error_value, error_traceback);
-}
-
-void
-PyFrame_LocalsToFast(PyFrameObject *f, int clear)
-{
- /* Merge f->f_locals into fast locals */
- PyObject *locals, *map;
- PyObject **fast;
- PyObject *error_type, *error_value, *error_traceback;
- PyCodeObject *co;
- Py_ssize_t j;
- int ncells, nfreevars;
- if (f == NULL)
- return;
- locals = f->f_locals;
- co = f->f_code;
- map = co->co_varnames;
- if (locals == NULL)
- return;
- if (!PyTuple_Check(map))
- return;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
- fast = f->f_localsplus;
- j = PyTuple_GET_SIZE(map);
- if (j > co->co_nlocals)
- j = co->co_nlocals;
- if (co->co_nlocals)
- dict_to_map(co->co_varnames, j, locals, fast, 0, clear);
- ncells = PyTuple_GET_SIZE(co->co_cellvars);
- nfreevars = PyTuple_GET_SIZE(co->co_freevars);
- if (ncells || nfreevars) {
- dict_to_map(co->co_cellvars, ncells,
- locals, fast + co->co_nlocals, 1, clear);
- dict_to_map(co->co_freevars, nfreevars,
- locals, fast + co->co_nlocals + ncells, 1,
- clear);
- }
- PyErr_Restore(error_type, error_value, error_traceback);
-}
-
-/* Clear out the free list */
-
-void
-PyFrame_Fini(void)
-{
- while (free_list != NULL) {
- PyFrameObject *f = free_list;
- free_list = free_list->f_back;
- PyObject_GC_Del(f);
- --numfree;
- }
- assert(numfree == 0);
- Py_XDECREF(builtin_object);
- builtin_object = NULL;
-}
diff --git a/sys/src/cmd/python/Objects/funcobject.c b/sys/src/cmd/python/Objects/funcobject.c
deleted file mode 100644
index 1ba74c5a9..000000000
--- a/sys/src/cmd/python/Objects/funcobject.c
+++ /dev/null
@@ -1,888 +0,0 @@
-
-/* Function object implementation */
-
-#include "Python.h"
-#include "code.h"
-#include "eval.h"
-#include "structmember.h"
-
-PyObject *
-PyFunction_New(PyObject *code, PyObject *globals)
-{
- PyFunctionObject *op = PyObject_GC_New(PyFunctionObject,
- &PyFunction_Type);
- static PyObject *__name__ = 0;
- if (op != NULL) {
- PyObject *doc;
- PyObject *consts;
- PyObject *module;
- op->func_weakreflist = NULL;
- Py_INCREF(code);
- op->func_code = code;
- Py_INCREF(globals);
- op->func_globals = globals;
- op->func_name = ((PyCodeObject *)code)->co_name;
- Py_INCREF(op->func_name);
- op->func_defaults = NULL; /* No default arguments */
- op->func_closure = NULL;
- consts = ((PyCodeObject *)code)->co_consts;
- if (PyTuple_Size(consts) >= 1) {
- doc = PyTuple_GetItem(consts, 0);
- if (!PyString_Check(doc) && !PyUnicode_Check(doc))
- doc = Py_None;
- }
- else
- doc = Py_None;
- Py_INCREF(doc);
- op->func_doc = doc;
- op->func_dict = NULL;
- op->func_module = NULL;
-
- /* __module__: If module name is in globals, use it.
- Otherwise, use None.
- */
- if (!__name__) {
- __name__ = PyString_InternFromString("__name__");
- if (!__name__) {
- Py_DECREF(op);
- return NULL;
- }
- }
- module = PyDict_GetItem(globals, __name__);
- if (module) {
- Py_INCREF(module);
- op->func_module = module;
- }
- }
- else
- return NULL;
- _PyObject_GC_TRACK(op);
- return (PyObject *)op;
-}
-
-PyObject *
-PyFunction_GetCode(PyObject *op)
-{
- if (!PyFunction_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyFunctionObject *) op) -> func_code;
-}
-
-PyObject *
-PyFunction_GetGlobals(PyObject *op)
-{
- if (!PyFunction_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyFunctionObject *) op) -> func_globals;
-}
-
-PyObject *
-PyFunction_GetModule(PyObject *op)
-{
- if (!PyFunction_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyFunctionObject *) op) -> func_module;
-}
-
-PyObject *
-PyFunction_GetDefaults(PyObject *op)
-{
- if (!PyFunction_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyFunctionObject *) op) -> func_defaults;
-}
-
-int
-PyFunction_SetDefaults(PyObject *op, PyObject *defaults)
-{
- if (!PyFunction_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (defaults == Py_None)
- defaults = NULL;
- else if (defaults && PyTuple_Check(defaults)) {
- Py_INCREF(defaults);
- }
- else {
- PyErr_SetString(PyExc_SystemError, "non-tuple default args");
- return -1;
- }
- Py_XDECREF(((PyFunctionObject *) op) -> func_defaults);
- ((PyFunctionObject *) op) -> func_defaults = defaults;
- return 0;
-}
-
-PyObject *
-PyFunction_GetClosure(PyObject *op)
-{
- if (!PyFunction_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyFunctionObject *) op) -> func_closure;
-}
-
-int
-PyFunction_SetClosure(PyObject *op, PyObject *closure)
-{
- if (!PyFunction_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (closure == Py_None)
- closure = NULL;
- else if (PyTuple_Check(closure)) {
- Py_INCREF(closure);
- }
- else {
- PyErr_Format(PyExc_SystemError,
- "expected tuple for closure, got '%.100s'",
- closure->ob_type->tp_name);
- return -1;
- }
- Py_XDECREF(((PyFunctionObject *) op) -> func_closure);
- ((PyFunctionObject *) op) -> func_closure = closure;
- return 0;
-}
-
-/* Methods */
-
-#define OFF(x) offsetof(PyFunctionObject, x)
-
-static PyMemberDef func_memberlist[] = {
- {"func_closure", T_OBJECT, OFF(func_closure),
- RESTRICTED|READONLY},
- {"func_doc", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
- {"__doc__", T_OBJECT, OFF(func_doc), WRITE_RESTRICTED},
- {"func_globals", T_OBJECT, OFF(func_globals),
- RESTRICTED|READONLY},
- {"__module__", T_OBJECT, OFF(func_module), WRITE_RESTRICTED},
- {NULL} /* Sentinel */
-};
-
-static int
-restricted(void)
-{
- if (!PyEval_GetRestricted())
- return 0;
- PyErr_SetString(PyExc_RuntimeError,
- "function attributes not accessible in restricted mode");
- return 1;
-}
-
-static PyObject *
-func_get_dict(PyFunctionObject *op)
-{
- if (restricted())
- return NULL;
- if (op->func_dict == NULL) {
- op->func_dict = PyDict_New();
- if (op->func_dict == NULL)
- return NULL;
- }
- Py_INCREF(op->func_dict);
- return op->func_dict;
-}
-
-static int
-func_set_dict(PyFunctionObject *op, PyObject *value)
-{
- PyObject *tmp;
-
- if (restricted())
- return -1;
- /* It is illegal to del f.func_dict */
- if (value == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "function's dictionary may not be deleted");
- return -1;
- }
- /* Can only set func_dict to a dictionary */
- if (!PyDict_Check(value)) {
- PyErr_SetString(PyExc_TypeError,
- "setting function's dictionary to a non-dict");
- return -1;
- }
- tmp = op->func_dict;
- Py_INCREF(value);
- op->func_dict = value;
- Py_XDECREF(tmp);
- return 0;
-}
-
-static PyObject *
-func_get_code(PyFunctionObject *op)
-{
- if (restricted())
- return NULL;
- Py_INCREF(op->func_code);
- return op->func_code;
-}
-
-static int
-func_set_code(PyFunctionObject *op, PyObject *value)
-{
- PyObject *tmp;
- Py_ssize_t nfree, nclosure;
-
- if (restricted())
- return -1;
- /* Not legal to del f.func_code or to set it to anything
- * other than a code object. */
- if (value == NULL || !PyCode_Check(value)) {
- PyErr_SetString(PyExc_TypeError,
- "func_code must be set to a code object");
- return -1;
- }
- nfree = PyCode_GetNumFree((PyCodeObject *)value);
- nclosure = (op->func_closure == NULL ? 0 :
- PyTuple_GET_SIZE(op->func_closure));
- if (nclosure != nfree) {
- PyErr_Format(PyExc_ValueError,
- "%s() requires a code object with %zd free vars,"
- " not %zd",
- PyString_AsString(op->func_name),
- nclosure, nfree);
- return -1;
- }
- tmp = op->func_code;
- Py_INCREF(value);
- op->func_code = value;
- Py_DECREF(tmp);
- return 0;
-}
-
-static PyObject *
-func_get_name(PyFunctionObject *op)
-{
- Py_INCREF(op->func_name);
- return op->func_name;
-}
-
-static int
-func_set_name(PyFunctionObject *op, PyObject *value)
-{
- PyObject *tmp;
-
- if (restricted())
- return -1;
- /* Not legal to del f.func_name or to set it to anything
- * other than a string object. */
- if (value == NULL || !PyString_Check(value)) {
- PyErr_SetString(PyExc_TypeError,
- "func_name must be set to a string object");
- return -1;
- }
- tmp = op->func_name;
- Py_INCREF(value);
- op->func_name = value;
- Py_DECREF(tmp);
- return 0;
-}
-
-static PyObject *
-func_get_defaults(PyFunctionObject *op)
-{
- if (restricted())
- return NULL;
- if (op->func_defaults == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- Py_INCREF(op->func_defaults);
- return op->func_defaults;
-}
-
-static int
-func_set_defaults(PyFunctionObject *op, PyObject *value)
-{
- PyObject *tmp;
-
- if (restricted())
- return -1;
- /* Legal to del f.func_defaults.
- * Can only set func_defaults to NULL or a tuple. */
- if (value == Py_None)
- value = NULL;
- if (value != NULL && !PyTuple_Check(value)) {
- PyErr_SetString(PyExc_TypeError,
- "func_defaults must be set to a tuple object");
- return -1;
- }
- tmp = op->func_defaults;
- Py_XINCREF(value);
- op->func_defaults = value;
- Py_XDECREF(tmp);
- return 0;
-}
-
-static PyGetSetDef func_getsetlist[] = {
- {"func_code", (getter)func_get_code, (setter)func_set_code},
- {"func_defaults", (getter)func_get_defaults,
- (setter)func_set_defaults},
- {"func_dict", (getter)func_get_dict, (setter)func_set_dict},
- {"__dict__", (getter)func_get_dict, (setter)func_set_dict},
- {"func_name", (getter)func_get_name, (setter)func_set_name},
- {"__name__", (getter)func_get_name, (setter)func_set_name},
- {NULL} /* Sentinel */
-};
-
-PyDoc_STRVAR(func_doc,
-"function(code, globals[, name[, argdefs[, closure]]])\n\
-\n\
-Create a function object from a code object and a dictionary.\n\
-The optional name string overrides the name from the code object.\n\
-The optional argdefs tuple specifies the default argument values.\n\
-The optional closure tuple supplies the bindings for free variables.");
-
-/* func_new() maintains the following invariants for closures. The
- closure must correspond to the free variables of the code object.
-
- if len(code.co_freevars) == 0:
- closure = NULL
- else:
- len(closure) == len(code.co_freevars)
- for every elt in closure, type(elt) == cell
-*/
-
-static PyObject *
-func_new(PyTypeObject* type, PyObject* args, PyObject* kw)
-{
- PyCodeObject *code;
- PyObject *globals;
- PyObject *name = Py_None;
- PyObject *defaults = Py_None;
- PyObject *closure = Py_None;
- PyFunctionObject *newfunc;
- Py_ssize_t nfree, nclosure;
- static char *kwlist[] = {"code", "globals", "name",
- "argdefs", "closure", 0};
-
- if (!PyArg_ParseTupleAndKeywords(args, kw, "O!O!|OOO:function",
- kwlist,
- &PyCode_Type, &code,
- &PyDict_Type, &globals,
- &name, &defaults, &closure))
- return NULL;
- if (name != Py_None && !PyString_Check(name)) {
- PyErr_SetString(PyExc_TypeError,
- "arg 3 (name) must be None or string");
- return NULL;
- }
- if (defaults != Py_None && !PyTuple_Check(defaults)) {
- PyErr_SetString(PyExc_TypeError,
- "arg 4 (defaults) must be None or tuple");
- return NULL;
- }
- nfree = PyTuple_GET_SIZE(code->co_freevars);
- if (!PyTuple_Check(closure)) {
- if (nfree && closure == Py_None) {
- PyErr_SetString(PyExc_TypeError,
- "arg 5 (closure) must be tuple");
- return NULL;
- }
- else if (closure != Py_None) {
- PyErr_SetString(PyExc_TypeError,
- "arg 5 (closure) must be None or tuple");
- return NULL;
- }
- }
-
- /* check that the closure is well-formed */
- nclosure = closure == Py_None ? 0 : PyTuple_GET_SIZE(closure);
- if (nfree != nclosure)
- return PyErr_Format(PyExc_ValueError,
- "%s requires closure of length %zd, not %zd",
- PyString_AS_STRING(code->co_name),
- nfree, nclosure);
- if (nclosure) {
- Py_ssize_t i;
- for (i = 0; i < nclosure; i++) {
- PyObject *o = PyTuple_GET_ITEM(closure, i);
- if (!PyCell_Check(o)) {
- return PyErr_Format(PyExc_TypeError,
- "arg 5 (closure) expected cell, found %s",
- o->ob_type->tp_name);
- }
- }
- }
-
- newfunc = (PyFunctionObject *)PyFunction_New((PyObject *)code,
- globals);
- if (newfunc == NULL)
- return NULL;
-
- if (name != Py_None) {
- Py_INCREF(name);
- Py_DECREF(newfunc->func_name);
- newfunc->func_name = name;
- }
- if (defaults != Py_None) {
- Py_INCREF(defaults);
- newfunc->func_defaults = defaults;
- }
- if (closure != Py_None) {
- Py_INCREF(closure);
- newfunc->func_closure = closure;
- }
-
- return (PyObject *)newfunc;
-}
-
-static void
-func_dealloc(PyFunctionObject *op)
-{
- _PyObject_GC_UNTRACK(op);
- if (op->func_weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) op);
- Py_DECREF(op->func_code);
- Py_DECREF(op->func_globals);
- Py_XDECREF(op->func_module);
- Py_DECREF(op->func_name);
- Py_XDECREF(op->func_defaults);
- Py_XDECREF(op->func_doc);
- Py_XDECREF(op->func_dict);
- Py_XDECREF(op->func_closure);
- PyObject_GC_Del(op);
-}
-
-static PyObject*
-func_repr(PyFunctionObject *op)
-{
- return PyString_FromFormat("<function %s at %p>",
- PyString_AsString(op->func_name),
- op);
-}
-
-static int
-func_traverse(PyFunctionObject *f, visitproc visit, void *arg)
-{
- Py_VISIT(f->func_code);
- Py_VISIT(f->func_globals);
- Py_VISIT(f->func_module);
- Py_VISIT(f->func_defaults);
- Py_VISIT(f->func_doc);
- Py_VISIT(f->func_name);
- Py_VISIT(f->func_dict);
- Py_VISIT(f->func_closure);
- return 0;
-}
-
-static PyObject *
-function_call(PyObject *func, PyObject *arg, PyObject *kw)
-{
- PyObject *result;
- PyObject *argdefs;
- PyObject **d, **k;
- Py_ssize_t nk, nd;
-
- argdefs = PyFunction_GET_DEFAULTS(func);
- if (argdefs != NULL && PyTuple_Check(argdefs)) {
- d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0);
- nd = PyTuple_Size(argdefs);
- }
- else {
- d = NULL;
- nd = 0;
- }
-
- if (kw != NULL && PyDict_Check(kw)) {
- Py_ssize_t pos, i;
- nk = PyDict_Size(kw);
- k = PyMem_NEW(PyObject *, 2*nk);
- if (k == NULL) {
- PyErr_NoMemory();
- return NULL;
- }
- pos = i = 0;
- while (PyDict_Next(kw, &pos, &k[i], &k[i+1]))
- i += 2;
- nk = i/2;
- /* XXX This is broken if the caller deletes dict items! */
- }
- else {
- k = NULL;
- nk = 0;
- }
-
- result = PyEval_EvalCodeEx(
- (PyCodeObject *)PyFunction_GET_CODE(func),
- PyFunction_GET_GLOBALS(func), (PyObject *)NULL,
- &PyTuple_GET_ITEM(arg, 0), PyTuple_Size(arg),
- k, nk, d, nd,
- PyFunction_GET_CLOSURE(func));
-
- if (k != NULL)
- PyMem_DEL(k);
-
- return result;
-}
-
-/* Bind a function to an object */
-static PyObject *
-func_descr_get(PyObject *func, PyObject *obj, PyObject *type)
-{
- if (obj == Py_None)
- obj = NULL;
- return PyMethod_New(func, obj, type);
-}
-
-PyTypeObject PyFunction_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "function",
- sizeof(PyFunctionObject),
- 0,
- (destructor)func_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)func_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- function_call, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- func_doc, /* tp_doc */
- (traverseproc)func_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- func_memberlist, /* tp_members */
- func_getsetlist, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- func_descr_get, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(PyFunctionObject, func_dict), /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- func_new, /* tp_new */
-};
-
-
-/* Class method object */
-
-/* A class method receives the class as implicit first argument,
- just like an instance method receives the instance.
- To declare a class method, use this idiom:
-
- class C:
- def f(cls, arg1, arg2, ...): ...
- f = classmethod(f)
-
- It can be called either on the class (e.g. C.f()) or on an instance
- (e.g. C().f()); the instance is ignored except for its class.
- If a class method is called for a derived class, the derived class
- object is passed as the implied first argument.
-
- Class methods are different than C++ or Java static methods.
- If you want those, see static methods below.
-*/
-
-typedef struct {
- PyObject_HEAD
- PyObject *cm_callable;
-} classmethod;
-
-static void
-cm_dealloc(classmethod *cm)
-{
- _PyObject_GC_UNTRACK((PyObject *)cm);
- Py_XDECREF(cm->cm_callable);
- cm->ob_type->tp_free((PyObject *)cm);
-}
-
-static int
-cm_traverse(classmethod *cm, visitproc visit, void *arg)
-{
- Py_VISIT(cm->cm_callable);
- return 0;
-}
-
-static int
-cm_clear(classmethod *cm)
-{
- Py_CLEAR(cm->cm_callable);
- return 0;
-}
-
-
-static PyObject *
-cm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
-{
- classmethod *cm = (classmethod *)self;
-
- if (cm->cm_callable == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "uninitialized classmethod object");
- return NULL;
- }
- if (type == NULL)
- type = (PyObject *)(obj->ob_type);
- return PyMethod_New(cm->cm_callable,
- type, (PyObject *)(type->ob_type));
-}
-
-static int
-cm_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- classmethod *cm = (classmethod *)self;
- PyObject *callable;
-
- if (!PyArg_UnpackTuple(args, "classmethod", 1, 1, &callable))
- return -1;
- if (!_PyArg_NoKeywords("classmethod", kwds))
- return -1;
- if (!PyCallable_Check(callable)) {
- PyErr_Format(PyExc_TypeError, "'%s' object is not callable",
- callable->ob_type->tp_name);
- return -1;
- }
-
- Py_INCREF(callable);
- cm->cm_callable = callable;
- return 0;
-}
-
-PyDoc_STRVAR(classmethod_doc,
-"classmethod(function) -> method\n\
-\n\
-Convert a function to be a class method.\n\
-\n\
-A class method receives the class as implicit first argument,\n\
-just like an instance method receives the instance.\n\
-To declare a class method, use this idiom:\n\
-\n\
- class C:\n\
- def f(cls, arg1, arg2, ...): ...\n\
- f = classmethod(f)\n\
-\n\
-It can be called either on the class (e.g. C.f()) or on an instance\n\
-(e.g. C().f()). The instance is ignored except for its class.\n\
-If a class method is called for a derived class, the derived class\n\
-object is passed as the implied first argument.\n\
-\n\
-Class methods are different than C++ or Java static methods.\n\
-If you want those, see the staticmethod builtin.");
-
-PyTypeObject PyClassMethod_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "classmethod",
- sizeof(classmethod),
- 0,
- (destructor)cm_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- classmethod_doc, /* tp_doc */
- (traverseproc)cm_traverse, /* tp_traverse */
- (inquiry)cm_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- cm_descr_get, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- cm_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-PyObject *
-PyClassMethod_New(PyObject *callable)
-{
- classmethod *cm = (classmethod *)
- PyType_GenericAlloc(&PyClassMethod_Type, 0);
- if (cm != NULL) {
- Py_INCREF(callable);
- cm->cm_callable = callable;
- }
- return (PyObject *)cm;
-}
-
-
-/* Static method object */
-
-/* A static method does not receive an implicit first argument.
- To declare a static method, use this idiom:
-
- class C:
- def f(arg1, arg2, ...): ...
- f = staticmethod(f)
-
- It can be called either on the class (e.g. C.f()) or on an instance
- (e.g. C().f()); the instance is ignored except for its class.
-
- Static methods in Python are similar to those found in Java or C++.
- For a more advanced concept, see class methods above.
-*/
-
-typedef struct {
- PyObject_HEAD
- PyObject *sm_callable;
-} staticmethod;
-
-static void
-sm_dealloc(staticmethod *sm)
-{
- _PyObject_GC_UNTRACK((PyObject *)sm);
- Py_XDECREF(sm->sm_callable);
- sm->ob_type->tp_free((PyObject *)sm);
-}
-
-static int
-sm_traverse(staticmethod *sm, visitproc visit, void *arg)
-{
- Py_VISIT(sm->sm_callable);
- return 0;
-}
-
-static int
-sm_clear(staticmethod *sm)
-{
- Py_XDECREF(sm->sm_callable);
- sm->sm_callable = NULL;
-
- return 0;
-}
-
-static PyObject *
-sm_descr_get(PyObject *self, PyObject *obj, PyObject *type)
-{
- staticmethod *sm = (staticmethod *)self;
-
- if (sm->sm_callable == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "uninitialized staticmethod object");
- return NULL;
- }
- Py_INCREF(sm->sm_callable);
- return sm->sm_callable;
-}
-
-static int
-sm_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- staticmethod *sm = (staticmethod *)self;
- PyObject *callable;
-
- if (!PyArg_UnpackTuple(args, "staticmethod", 1, 1, &callable))
- return -1;
- if (!_PyArg_NoKeywords("staticmethod", kwds))
- return -1;
- Py_INCREF(callable);
- sm->sm_callable = callable;
- return 0;
-}
-
-PyDoc_STRVAR(staticmethod_doc,
-"staticmethod(function) -> method\n\
-\n\
-Convert a function to be a static method.\n\
-\n\
-A static method does not receive an implicit first argument.\n\
-To declare a static method, use this idiom:\n\
-\n\
- class C:\n\
- def f(arg1, arg2, ...): ...\n\
- f = staticmethod(f)\n\
-\n\
-It can be called either on the class (e.g. C.f()) or on an instance\n\
-(e.g. C().f()). The instance is ignored except for its class.\n\
-\n\
-Static methods in Python are similar to those found in Java or C++.\n\
-For a more advanced concept, see the classmethod builtin.");
-
-PyTypeObject PyStaticMethod_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "staticmethod",
- sizeof(staticmethod),
- 0,
- (destructor)sm_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
- staticmethod_doc, /* tp_doc */
- (traverseproc)sm_traverse, /* tp_traverse */
- (inquiry)sm_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- sm_descr_get, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- sm_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-PyObject *
-PyStaticMethod_New(PyObject *callable)
-{
- staticmethod *sm = (staticmethod *)
- PyType_GenericAlloc(&PyStaticMethod_Type, 0);
- if (sm != NULL) {
- Py_INCREF(callable);
- sm->sm_callable = callable;
- }
- return (PyObject *)sm;
-}
diff --git a/sys/src/cmd/python/Objects/genobject.c b/sys/src/cmd/python/Objects/genobject.c
deleted file mode 100644
index 4d0c4f6ee..000000000
--- a/sys/src/cmd/python/Objects/genobject.c
+++ /dev/null
@@ -1,383 +0,0 @@
-/* Generator object implementation */
-
-#include "Python.h"
-#include "frameobject.h"
-#include "genobject.h"
-#include "ceval.h"
-#include "structmember.h"
-#include "opcode.h"
-
-static int
-gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
-{
- Py_VISIT((PyObject *)gen->gi_frame);
- return 0;
-}
-
-static void
-gen_dealloc(PyGenObject *gen)
-{
- PyObject *self = (PyObject *) gen;
-
- _PyObject_GC_UNTRACK(gen);
-
- if (gen->gi_weakreflist != NULL)
- PyObject_ClearWeakRefs(self);
-
- _PyObject_GC_TRACK(self);
-
- if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) {
- /* Generator is paused, so we need to close */
- gen->ob_type->tp_del(self);
- if (self->ob_refcnt > 0)
- return; /* resurrected. :( */
- }
-
- _PyObject_GC_UNTRACK(self);
- Py_CLEAR(gen->gi_frame);
- PyObject_GC_Del(gen);
-}
-
-
-static PyObject *
-gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
-{
- PyThreadState *tstate = PyThreadState_GET();
- PyFrameObject *f = gen->gi_frame;
- PyObject *result;
-
- if (gen->gi_running) {
- PyErr_SetString(PyExc_ValueError,
- "generator already executing");
- return NULL;
- }
- if (f==NULL || f->f_stacktop == NULL) {
- /* Only set exception if called from send() */
- if (arg && !exc)
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
-
- if (f->f_lasti == -1) {
- if (arg && arg != Py_None) {
- PyErr_SetString(PyExc_TypeError,
- "can't send non-None value to a "
- "just-started generator");
- return NULL;
- }
- } else {
- /* Push arg onto the frame's value stack */
- result = arg ? arg : Py_None;
- Py_INCREF(result);
- *(f->f_stacktop++) = result;
- }
-
- /* Generators always return to their most recent caller, not
- * necessarily their creator. */
- Py_XINCREF(tstate->frame);
- assert(f->f_back == NULL);
- f->f_back = tstate->frame;
-
- gen->gi_running = 1;
- result = PyEval_EvalFrameEx(f, exc);
- gen->gi_running = 0;
-
- /* Don't keep the reference to f_back any longer than necessary. It
- * may keep a chain of frames alive or it could create a reference
- * cycle. */
- assert(f->f_back == tstate->frame);
- Py_CLEAR(f->f_back);
-
- /* If the generator just returned (as opposed to yielding), signal
- * that the generator is exhausted. */
- if (result == Py_None && f->f_stacktop == NULL) {
- Py_DECREF(result);
- result = NULL;
- /* Set exception if not called by gen_iternext() */
- if (arg)
- PyErr_SetNone(PyExc_StopIteration);
- }
-
- if (!result || f->f_stacktop == NULL) {
- /* generator can't be rerun, so release the frame */
- Py_DECREF(f);
- gen->gi_frame = NULL;
- }
-
- return result;
-}
-
-PyDoc_STRVAR(send_doc,
-"send(arg) -> send 'arg' into generator,\n\
-return next yielded value or raise StopIteration.");
-
-static PyObject *
-gen_send(PyGenObject *gen, PyObject *arg)
-{
- return gen_send_ex(gen, arg, 0);
-}
-
-PyDoc_STRVAR(close_doc,
-"close(arg) -> raise GeneratorExit inside generator.");
-
-static PyObject *
-gen_close(PyGenObject *gen, PyObject *args)
-{
- PyObject *retval;
- PyErr_SetNone(PyExc_GeneratorExit);
- retval = gen_send_ex(gen, Py_None, 1);
- if (retval) {
- Py_DECREF(retval);
- PyErr_SetString(PyExc_RuntimeError,
- "generator ignored GeneratorExit");
- return NULL;
- }
- if (PyErr_ExceptionMatches(PyExc_StopIteration)
- || PyErr_ExceptionMatches(PyExc_GeneratorExit))
- {
- PyErr_Clear(); /* ignore these errors */
- Py_INCREF(Py_None);
- return Py_None;
- }
- return NULL;
-}
-
-static void
-gen_del(PyObject *self)
-{
- PyObject *res;
- PyObject *error_type, *error_value, *error_traceback;
- PyGenObject *gen = (PyGenObject *)self;
-
- if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
- /* Generator isn't paused, so no need to close */
- return;
-
- /* Temporarily resurrect the object. */
- assert(self->ob_refcnt == 0);
- self->ob_refcnt = 1;
-
- /* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- res = gen_close(gen, NULL);
-
- if (res == NULL)
- PyErr_WriteUnraisable(self);
- else
- Py_DECREF(res);
-
- /* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
-
- /* Undo the temporary resurrection; can't use DECREF here, it would
- * cause a recursive call.
- */
- assert(self->ob_refcnt > 0);
- if (--self->ob_refcnt == 0)
- return; /* this is the normal path out */
-
- /* close() resurrected it! Make it look like the original Py_DECREF
- * never happened.
- */
- {
- Py_ssize_t refcnt = self->ob_refcnt;
- _Py_NewReference(self);
- self->ob_refcnt = refcnt;
- }
- assert(PyType_IS_GC(self->ob_type) &&
- _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
-
- /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
- * we need to undo that. */
- _Py_DEC_REFTOTAL;
- /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
- * chain, so no more to do there.
- * If COUNT_ALLOCS, the original decref bumped tp_frees, and
- * _Py_NewReference bumped tp_allocs: both of those need to be
- * undone.
- */
-#ifdef COUNT_ALLOCS
- --self->ob_type->tp_frees;
- --self->ob_type->tp_allocs;
-#endif
-}
-
-
-
-PyDoc_STRVAR(throw_doc,
-"throw(typ[,val[,tb]]) -> raise exception in generator,\n\
-return next yielded value or raise StopIteration.");
-
-static PyObject *
-gen_throw(PyGenObject *gen, PyObject *args)
-{
- PyObject *typ;
- PyObject *tb = NULL;
- PyObject *val = NULL;
-
- if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
- return NULL;
-
- /* First, check the traceback argument, replacing None with
- NULL. */
- if (tb == Py_None)
- tb = NULL;
- else if (tb != NULL && !PyTraceBack_Check(tb)) {
- PyErr_SetString(PyExc_TypeError,
- "throw() third argument must be a traceback object");
- return NULL;
- }
-
- Py_INCREF(typ);
- Py_XINCREF(val);
- Py_XINCREF(tb);
-
- if (PyExceptionClass_Check(typ)) {
- PyErr_NormalizeException(&typ, &val, &tb);
- }
-
- else if (PyExceptionInstance_Check(typ)) {
- /* Raising an instance. The value should be a dummy. */
- if (val && val != Py_None) {
- PyErr_SetString(PyExc_TypeError,
- "instance exception may not have a separate value");
- goto failed_throw;
- }
- else {
- /* Normalize to raise <class>, <instance> */
- Py_XDECREF(val);
- val = typ;
- typ = PyExceptionInstance_Class(typ);
- Py_INCREF(typ);
- }
- }
-
- /* Allow raising builtin string exceptions */
-
- else if (!PyString_CheckExact(typ)) {
- /* Not something you can raise. throw() fails. */
- PyErr_Format(PyExc_TypeError,
- "exceptions must be classes, or instances, not %s",
- typ->ob_type->tp_name);
- goto failed_throw;
- }
-
- PyErr_Restore(typ, val, tb);
- return gen_send_ex(gen, Py_None, 1);
-
-failed_throw:
- /* Didn't use our arguments, so restore their original refcounts */
- Py_DECREF(typ);
- Py_XDECREF(val);
- Py_XDECREF(tb);
- return NULL;
-}
-
-
-static PyObject *
-gen_iternext(PyGenObject *gen)
-{
- return gen_send_ex(gen, NULL, 0);
-}
-
-
-static PyMemberDef gen_memberlist[] = {
- {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), RO},
- {"gi_running", T_INT, offsetof(PyGenObject, gi_running), RO},
- {NULL} /* Sentinel */
-};
-
-static PyMethodDef gen_methods[] = {
- {"send",(PyCFunction)gen_send, METH_O, send_doc},
- {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
- {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
- {NULL, NULL} /* Sentinel */
-};
-
-PyTypeObject PyGen_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "generator", /* tp_name */
- sizeof(PyGenObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)gen_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)gen_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)gen_iternext, /* tp_iternext */
- gen_methods, /* tp_methods */
- gen_memberlist, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
-
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- 0, /* tp_free */
- 0, /* tp_is_gc */
- 0, /* tp_bases */
- 0, /* tp_mro */
- 0, /* tp_cache */
- 0, /* tp_subclasses */
- 0, /* tp_weaklist */
- gen_del, /* tp_del */
-};
-
-PyObject *
-PyGen_New(PyFrameObject *f)
-{
- PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
- if (gen == NULL) {
- Py_DECREF(f);
- return NULL;
- }
- gen->gi_frame = f;
- gen->gi_running = 0;
- gen->gi_weakreflist = NULL;
- _PyObject_GC_TRACK(gen);
- return (PyObject *)gen;
-}
-
-int
-PyGen_NeedsFinalizing(PyGenObject *gen)
-{
- int i;
- PyFrameObject *f = gen->gi_frame;
-
- if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0)
- return 0; /* no frame or empty blockstack == no finalization */
-
- /* Any block type besides a loop requires cleanup. */
- i = f->f_iblock;
- while (--i >= 0) {
- if (f->f_blockstack[i].b_type != SETUP_LOOP)
- return 1;
- }
-
- /* No blocks except loops, it's safe to skip finalization. */
- return 0;
-}
diff --git a/sys/src/cmd/python/Objects/intobject.c b/sys/src/cmd/python/Objects/intobject.c
deleted file mode 100644
index 8aa8d0b39..000000000
--- a/sys/src/cmd/python/Objects/intobject.c
+++ /dev/null
@@ -1,1280 +0,0 @@
-
-/* Integer object implementation */
-
-#include "Python.h"
-#include <ctype.h>
-
-long
-PyInt_GetMax(void)
-{
- return LONG_MAX; /* To initialize sys.maxint */
-}
-
-/* Integers are quite normal objects, to make object handling uniform.
- (Using odd pointers to represent integers would save much space
- but require extra checks for this special case throughout the code.)
- Since a typical Python program spends much of its time allocating
- and deallocating integers, these operations should be very fast.
- Therefore we use a dedicated allocation scheme with a much lower
- overhead (in space and time) than straight malloc(): a simple
- dedicated free list, filled when necessary with memory from malloc().
-
- block_list is a singly-linked list of all PyIntBlocks ever allocated,
- linked via their next members. PyIntBlocks are never returned to the
- system before shutdown (PyInt_Fini).
-
- free_list is a singly-linked list of available PyIntObjects, linked
- via abuse of their ob_type members.
-*/
-
-#define BLOCK_SIZE 1000 /* 1K less typical malloc overhead */
-#define BHEAD_SIZE 8 /* Enough for a 64-bit pointer */
-#define N_INTOBJECTS ((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyIntObject))
-
-struct _intblock {
- struct _intblock *next;
- PyIntObject objects[N_INTOBJECTS];
-};
-
-typedef struct _intblock PyIntBlock;
-
-static PyIntBlock *block_list = NULL;
-static PyIntObject *free_list = NULL;
-
-static PyIntObject *
-fill_free_list(void)
-{
- PyIntObject *p, *q;
- /* Python's object allocator isn't appropriate for large blocks. */
- p = (PyIntObject *) PyMem_MALLOC(sizeof(PyIntBlock));
- if (p == NULL)
- return (PyIntObject *) PyErr_NoMemory();
- ((PyIntBlock *)p)->next = block_list;
- block_list = (PyIntBlock *)p;
- /* Link the int objects together, from rear to front, then return
- the address of the last int object in the block. */
- p = &((PyIntBlock *)p)->objects[0];
- q = p + N_INTOBJECTS;
- while (--q > p)
- q->ob_type = (struct _typeobject *)(q-1);
- q->ob_type = NULL;
- return p + N_INTOBJECTS - 1;
-}
-
-#ifndef NSMALLPOSINTS
-#define NSMALLPOSINTS 257
-#endif
-#ifndef NSMALLNEGINTS
-#define NSMALLNEGINTS 5
-#endif
-#if NSMALLNEGINTS + NSMALLPOSINTS > 0
-/* References to small integers are saved in this array so that they
- can be shared.
- The integers that are saved are those in the range
- -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
-*/
-static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];
-#endif
-#ifdef COUNT_ALLOCS
-int quick_int_allocs, quick_neg_int_allocs;
-#endif
-
-PyObject *
-PyInt_FromLong(long ival)
-{
- register PyIntObject *v;
-#if NSMALLNEGINTS + NSMALLPOSINTS > 0
- if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) {
- v = small_ints[ival + NSMALLNEGINTS];
- Py_INCREF(v);
-#ifdef COUNT_ALLOCS
- if (ival >= 0)
- quick_int_allocs++;
- else
- quick_neg_int_allocs++;
-#endif
- return (PyObject *) v;
- }
-#endif
- if (free_list == NULL) {
- if ((free_list = fill_free_list()) == NULL)
- return NULL;
- }
- /* Inline PyObject_New */
- v = free_list;
- free_list = (PyIntObject *)v->ob_type;
- PyObject_INIT(v, &PyInt_Type);
- v->ob_ival = ival;
- return (PyObject *) v;
-}
-
-PyObject *
-PyInt_FromSize_t(size_t ival)
-{
- if (ival <= LONG_MAX)
- return PyInt_FromLong((long)ival);
- return _PyLong_FromSize_t(ival);
-}
-
-PyObject *
-PyInt_FromSsize_t(Py_ssize_t ival)
-{
- if (ival >= LONG_MIN && ival <= LONG_MAX)
- return PyInt_FromLong((long)ival);
- return _PyLong_FromSsize_t(ival);
-}
-
-static void
-int_dealloc(PyIntObject *v)
-{
- if (PyInt_CheckExact(v)) {
- v->ob_type = (struct _typeobject *)free_list;
- free_list = v;
- }
- else
- v->ob_type->tp_free((PyObject *)v);
-}
-
-static void
-int_free(PyIntObject *v)
-{
- v->ob_type = (struct _typeobject *)free_list;
- free_list = v;
-}
-
-long
-PyInt_AsLong(register PyObject *op)
-{
- PyNumberMethods *nb;
- PyIntObject *io;
- long val;
-
- if (op && PyInt_Check(op))
- return PyInt_AS_LONG((PyIntObject*) op);
-
- if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
- nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return -1;
- }
-
- io = (PyIntObject*) (*nb->nb_int) (op);
- if (io == NULL)
- return -1;
- if (!PyInt_Check(io)) {
- if (PyLong_Check(io)) {
- /* got a long? => retry int conversion */
- val = PyLong_AsLong((PyObject *)io);
- Py_DECREF(io);
- if ((val == -1) && PyErr_Occurred())
- return -1;
- return val;
- }
- else
- {
- Py_DECREF(io);
- PyErr_SetString(PyExc_TypeError,
- "nb_int should return int object");
- return -1;
- }
- }
-
- val = PyInt_AS_LONG(io);
- Py_DECREF(io);
-
- return val;
-}
-
-Py_ssize_t
-PyInt_AsSsize_t(register PyObject *op)
-{
-#if SIZEOF_SIZE_T != SIZEOF_LONG
- PyNumberMethods *nb;
- PyIntObject *io;
- Py_ssize_t val;
-#endif
-
- if (op == NULL) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return -1;
- }
-
- if (PyInt_Check(op))
- return PyInt_AS_LONG((PyIntObject*) op);
- if (PyLong_Check(op))
- return _PyLong_AsSsize_t(op);
-#if SIZEOF_SIZE_T == SIZEOF_LONG
- return PyInt_AsLong(op);
-#else
-
- if ((nb = op->ob_type->tp_as_number) == NULL ||
- (nb->nb_int == NULL && nb->nb_long == 0)) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return -1;
- }
-
- if (nb->nb_long != 0) {
- io = (PyIntObject*) (*nb->nb_long) (op);
- } else {
- io = (PyIntObject*) (*nb->nb_int) (op);
- }
- if (io == NULL)
- return -1;
- if (!PyInt_Check(io)) {
- if (PyLong_Check(io)) {
- /* got a long? => retry int conversion */
- val = _PyLong_AsSsize_t((PyObject *)io);
- Py_DECREF(io);
- if ((val == -1) && PyErr_Occurred())
- return -1;
- return val;
- }
- else
- {
- Py_DECREF(io);
- PyErr_SetString(PyExc_TypeError,
- "nb_int should return int object");
- return -1;
- }
- }
-
- val = PyInt_AS_LONG(io);
- Py_DECREF(io);
-
- return val;
-#endif
-}
-
-unsigned long
-PyInt_AsUnsignedLongMask(register PyObject *op)
-{
- PyNumberMethods *nb;
- PyIntObject *io;
- unsigned long val;
-
- if (op && PyInt_Check(op))
- return PyInt_AS_LONG((PyIntObject*) op);
- if (op && PyLong_Check(op))
- return PyLong_AsUnsignedLongMask(op);
-
- if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
- nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return (unsigned long)-1;
- }
-
- io = (PyIntObject*) (*nb->nb_int) (op);
- if (io == NULL)
- return (unsigned long)-1;
- if (!PyInt_Check(io)) {
- if (PyLong_Check(io)) {
- val = PyLong_AsUnsignedLongMask((PyObject *)io);
- Py_DECREF(io);
- if (PyErr_Occurred())
- return (unsigned long)-1;
- return val;
- }
- else
- {
- Py_DECREF(io);
- PyErr_SetString(PyExc_TypeError,
- "nb_int should return int object");
- return (unsigned long)-1;
- }
- }
-
- val = PyInt_AS_LONG(io);
- Py_DECREF(io);
-
- return val;
-}
-
-#ifdef HAVE_LONG_LONG
-unsigned PY_LONG_LONG
-PyInt_AsUnsignedLongLongMask(register PyObject *op)
-{
- PyNumberMethods *nb;
- PyIntObject *io;
- unsigned PY_LONG_LONG val;
-
- if (op && PyInt_Check(op))
- return PyInt_AS_LONG((PyIntObject*) op);
- if (op && PyLong_Check(op))
- return PyLong_AsUnsignedLongLongMask(op);
-
- if (op == NULL || (nb = op->ob_type->tp_as_number) == NULL ||
- nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return (unsigned PY_LONG_LONG)-1;
- }
-
- io = (PyIntObject*) (*nb->nb_int) (op);
- if (io == NULL)
- return (unsigned PY_LONG_LONG)-1;
- if (!PyInt_Check(io)) {
- if (PyLong_Check(io)) {
- val = PyLong_AsUnsignedLongLongMask((PyObject *)io);
- Py_DECREF(io);
- if (PyErr_Occurred())
- return (unsigned PY_LONG_LONG)-1;
- return val;
- }
- else
- {
- Py_DECREF(io);
- PyErr_SetString(PyExc_TypeError,
- "nb_int should return int object");
- return (unsigned PY_LONG_LONG)-1;
- }
- }
-
- val = PyInt_AS_LONG(io);
- Py_DECREF(io);
-
- return val;
-}
-#endif
-
-PyObject *
-PyInt_FromString(char *s, char **pend, int base)
-{
- char *end;
- long x;
- Py_ssize_t slen;
- PyObject *sobj, *srepr;
-
- if ((base != 0 && base < 2) || base > 36) {
- PyErr_SetString(PyExc_ValueError,
- "int() base must be >= 2 and <= 36");
- return NULL;
- }
-
- while (*s && isspace(Py_CHARMASK(*s)))
- s++;
- errno = 0;
- if (base == 0 && s[0] == '0') {
- x = (long) PyOS_strtoul(s, &end, base);
- if (x < 0)
- return PyLong_FromString(s, pend, base);
- }
- else
- x = PyOS_strtol(s, &end, base);
- if (end == s || !isalnum(Py_CHARMASK(end[-1])))
- goto bad;
- while (*end && isspace(Py_CHARMASK(*end)))
- end++;
- if (*end != '\0') {
- bad:
- slen = strlen(s) < 200 ? strlen(s) : 200;
- sobj = PyString_FromStringAndSize(s, slen);
- if (sobj == NULL)
- return NULL;
- srepr = PyObject_Repr(sobj);
- Py_DECREF(sobj);
- if (srepr == NULL)
- return NULL;
- PyErr_Format(PyExc_ValueError,
- "invalid literal for int() with base %d: %s",
- base, PyString_AS_STRING(srepr));
- Py_DECREF(srepr);
- return NULL;
- }
- else if (errno != 0)
- return PyLong_FromString(s, pend, base);
- if (pend)
- *pend = end;
- return PyInt_FromLong(x);
-}
-
-#ifdef Py_USING_UNICODE
-PyObject *
-PyInt_FromUnicode(Py_UNICODE *s, Py_ssize_t length, int base)
-{
- PyObject *result;
- char *buffer = (char *)PyMem_MALLOC(length+1);
-
- if (buffer == NULL)
- return NULL;
-
- if (PyUnicode_EncodeDecimal(s, length, buffer, NULL)) {
- PyMem_FREE(buffer);
- return NULL;
- }
- result = PyInt_FromString(buffer, NULL, base);
- PyMem_FREE(buffer);
- return result;
-}
-#endif
-
-/* Methods */
-
-/* Integers are seen as the "smallest" of all numeric types and thus
- don't have any knowledge about conversion of other types to
- integers. */
-
-#define CONVERT_TO_LONG(obj, lng) \
- if (PyInt_Check(obj)) { \
- lng = PyInt_AS_LONG(obj); \
- } \
- else { \
- Py_INCREF(Py_NotImplemented); \
- return Py_NotImplemented; \
- }
-
-/* ARGSUSED */
-static int
-int_print(PyIntObject *v, FILE *fp, int flags)
- /* flags -- not used but required by interface */
-{
- fprintf(fp, "%ld", v->ob_ival);
- return 0;
-}
-
-static PyObject *
-int_repr(PyIntObject *v)
-{
- char buf[64];
- PyOS_snprintf(buf, sizeof(buf), "%ld", v->ob_ival);
- return PyString_FromString(buf);
-}
-
-static int
-int_compare(PyIntObject *v, PyIntObject *w)
-{
- register long i = v->ob_ival;
- register long j = w->ob_ival;
- return (i < j) ? -1 : (i > j) ? 1 : 0;
-}
-
-static long
-int_hash(PyIntObject *v)
-{
- /* XXX If this is changed, you also need to change the way
- Python's long, float and complex types are hashed. */
- long x = v -> ob_ival;
- if (x == -1)
- x = -2;
- return x;
-}
-
-static PyObject *
-int_add(PyIntObject *v, PyIntObject *w)
-{
- register long a, b, x;
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- x = a + b;
- if ((x^a) >= 0 || (x^b) >= 0)
- return PyInt_FromLong(x);
- return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w);
-}
-
-static PyObject *
-int_sub(PyIntObject *v, PyIntObject *w)
-{
- register long a, b, x;
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- x = a - b;
- if ((x^a) >= 0 || (x^~b) >= 0)
- return PyInt_FromLong(x);
- return PyLong_Type.tp_as_number->nb_subtract((PyObject *)v,
- (PyObject *)w);
-}
-
-/*
-Integer overflow checking for * is painful: Python tried a couple ways, but
-they didn't work on all platforms, or failed in endcases (a product of
--sys.maxint-1 has been a particular pain).
-
-Here's another way:
-
-The native long product x*y is either exactly right or *way* off, being
-just the last n bits of the true product, where n is the number of bits
-in a long (the delivered product is the true product plus i*2**n for
-some integer i).
-
-The native double product (double)x * (double)y is subject to three
-rounding errors: on a sizeof(long)==8 box, each cast to double can lose
-info, and even on a sizeof(long)==4 box, the multiplication can lose info.
-But, unlike the native long product, it's not in *range* trouble: even
-if sizeof(long)==32 (256-bit longs), the product easily fits in the
-dynamic range of a double. So the leading 50 (or so) bits of the double
-product are correct.
-
-We check these two ways against each other, and declare victory if they're
-approximately the same. Else, because the native long product is the only
-one that can lose catastrophic amounts of information, it's the native long
-product that must have overflowed.
-*/
-
-static PyObject *
-int_mul(PyObject *v, PyObject *w)
-{
- long a, b;
- long longprod; /* a*b in native long arithmetic */
- double doubled_longprod; /* (double)longprod */
- double doubleprod; /* (double)a * (double)b */
-
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- longprod = a * b;
- doubleprod = (double)a * (double)b;
- doubled_longprod = (double)longprod;
-
- /* Fast path for normal case: small multiplicands, and no info
- is lost in either method. */
- if (doubled_longprod == doubleprod)
- return PyInt_FromLong(longprod);
-
- /* Somebody somewhere lost info. Close enough, or way off? Note
- that a != 0 and b != 0 (else doubled_longprod == doubleprod == 0).
- The difference either is or isn't significant compared to the
- true value (of which doubleprod is a good approximation).
- */
- {
- const double diff = doubled_longprod - doubleprod;
- const double absdiff = diff >= 0.0 ? diff : -diff;
- const double absprod = doubleprod >= 0.0 ? doubleprod :
- -doubleprod;
- /* absdiff/absprod <= 1/32 iff
- 32 * absdiff <= absprod -- 5 good bits is "close enough" */
- if (32.0 * absdiff <= absprod)
- return PyInt_FromLong(longprod);
- else
- return PyLong_Type.tp_as_number->nb_multiply(v, w);
- }
-}
-
-/* Integer overflow checking for unary negation: on a 2's-complement
- * box, -x overflows iff x is the most negative long. In this case we
- * get -x == x. However, -x is undefined (by C) if x /is/ the most
- * negative long (it's a signed overflow case), and some compilers care.
- * So we cast x to unsigned long first. However, then other compilers
- * warn about applying unary minus to an unsigned operand. Hence the
- * weird "0-".
- */
-#define UNARY_NEG_WOULD_OVERFLOW(x) \
- ((x) < 0 && (unsigned long)(x) == 0-(unsigned long)(x))
-
-/* Return type of i_divmod */
-enum divmod_result {
- DIVMOD_OK, /* Correct result */
- DIVMOD_OVERFLOW, /* Overflow, try again using longs */
- DIVMOD_ERROR /* Exception raised */
-};
-
-static enum divmod_result
-i_divmod(register long x, register long y,
- long *p_xdivy, long *p_xmody)
-{
- long xdivy, xmody;
-
- if (y == 0) {
- PyErr_SetString(PyExc_ZeroDivisionError,
- "integer division or modulo by zero");
- return DIVMOD_ERROR;
- }
- /* (-sys.maxint-1)/-1 is the only overflow case. */
- if (y == -1 && UNARY_NEG_WOULD_OVERFLOW(x))
- return DIVMOD_OVERFLOW;
- xdivy = x / y;
- xmody = x - xdivy * y;
- /* If the signs of x and y differ, and the remainder is non-0,
- * C89 doesn't define whether xdivy is now the floor or the
- * ceiling of the infinitely precise quotient. We want the floor,
- * and we have it iff the remainder's sign matches y's.
- */
- if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) {
- xmody += y;
- --xdivy;
- assert(xmody && ((y ^ xmody) >= 0));
- }
- *p_xdivy = xdivy;
- *p_xmody = xmody;
- return DIVMOD_OK;
-}
-
-static PyObject *
-int_div(PyIntObject *x, PyIntObject *y)
-{
- long xi, yi;
- long d, m;
- CONVERT_TO_LONG(x, xi);
- CONVERT_TO_LONG(y, yi);
- switch (i_divmod(xi, yi, &d, &m)) {
- case DIVMOD_OK:
- return PyInt_FromLong(d);
- case DIVMOD_OVERFLOW:
- return PyLong_Type.tp_as_number->nb_divide((PyObject *)x,
- (PyObject *)y);
- default:
- return NULL;
- }
-}
-
-static PyObject *
-int_classic_div(PyIntObject *x, PyIntObject *y)
-{
- long xi, yi;
- long d, m;
- CONVERT_TO_LONG(x, xi);
- CONVERT_TO_LONG(y, yi);
- if (Py_DivisionWarningFlag &&
- PyErr_Warn(PyExc_DeprecationWarning, "classic int division") < 0)
- return NULL;
- switch (i_divmod(xi, yi, &d, &m)) {
- case DIVMOD_OK:
- return PyInt_FromLong(d);
- case DIVMOD_OVERFLOW:
- return PyLong_Type.tp_as_number->nb_divide((PyObject *)x,
- (PyObject *)y);
- default:
- return NULL;
- }
-}
-
-static PyObject *
-int_true_divide(PyObject *v, PyObject *w)
-{
- /* If they aren't both ints, give someone else a chance. In
- particular, this lets int/long get handled by longs, which
- underflows to 0 gracefully if the long is too big to convert
- to float. */
- if (PyInt_Check(v) && PyInt_Check(w))
- return PyFloat_Type.tp_as_number->nb_true_divide(v, w);
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-static PyObject *
-int_mod(PyIntObject *x, PyIntObject *y)
-{
- long xi, yi;
- long d, m;
- CONVERT_TO_LONG(x, xi);
- CONVERT_TO_LONG(y, yi);
- switch (i_divmod(xi, yi, &d, &m)) {
- case DIVMOD_OK:
- return PyInt_FromLong(m);
- case DIVMOD_OVERFLOW:
- return PyLong_Type.tp_as_number->nb_remainder((PyObject *)x,
- (PyObject *)y);
- default:
- return NULL;
- }
-}
-
-static PyObject *
-int_divmod(PyIntObject *x, PyIntObject *y)
-{
- long xi, yi;
- long d, m;
- CONVERT_TO_LONG(x, xi);
- CONVERT_TO_LONG(y, yi);
- switch (i_divmod(xi, yi, &d, &m)) {
- case DIVMOD_OK:
- return Py_BuildValue("(ll)", d, m);
- case DIVMOD_OVERFLOW:
- return PyLong_Type.tp_as_number->nb_divmod((PyObject *)x,
- (PyObject *)y);
- default:
- return NULL;
- }
-}
-
-static PyObject *
-int_pow(PyIntObject *v, PyIntObject *w, PyIntObject *z)
-{
- register long iv, iw, iz=0, ix, temp, prev;
- CONVERT_TO_LONG(v, iv);
- CONVERT_TO_LONG(w, iw);
- if (iw < 0) {
- if ((PyObject *)z != Py_None) {
- PyErr_SetString(PyExc_TypeError, "pow() 2nd argument "
- "cannot be negative when 3rd argument specified");
- return NULL;
- }
- /* Return a float. This works because we know that
- this calls float_pow() which converts its
- arguments to double. */
- return PyFloat_Type.tp_as_number->nb_power(
- (PyObject *)v, (PyObject *)w, (PyObject *)z);
- }
- if ((PyObject *)z != Py_None) {
- CONVERT_TO_LONG(z, iz);
- if (iz == 0) {
- PyErr_SetString(PyExc_ValueError,
- "pow() 3rd argument cannot be 0");
- return NULL;
- }
- }
- /*
- * XXX: The original exponentiation code stopped looping
- * when temp hit zero; this code will continue onwards
- * unnecessarily, but at least it won't cause any errors.
- * Hopefully the speed improvement from the fast exponentiation
- * will compensate for the slight inefficiency.
- * XXX: Better handling of overflows is desperately needed.
- */
- temp = iv;
- ix = 1;
- while (iw > 0) {
- prev = ix; /* Save value for overflow check */
- if (iw & 1) {
- ix = ix*temp;
- if (temp == 0)
- break; /* Avoid ix / 0 */
- if (ix / temp != prev) {
- return PyLong_Type.tp_as_number->nb_power(
- (PyObject *)v,
- (PyObject *)w,
- (PyObject *)z);
- }
- }
- iw >>= 1; /* Shift exponent down by 1 bit */
- if (iw==0) break;
- prev = temp;
- temp *= temp; /* Square the value of temp */
- if (prev != 0 && temp / prev != prev) {
- return PyLong_Type.tp_as_number->nb_power(
- (PyObject *)v, (PyObject *)w, (PyObject *)z);
- }
- if (iz) {
- /* If we did a multiplication, perform a modulo */
- ix = ix % iz;
- temp = temp % iz;
- }
- }
- if (iz) {
- long div, mod;
- switch (i_divmod(ix, iz, &div, &mod)) {
- case DIVMOD_OK:
- ix = mod;
- break;
- case DIVMOD_OVERFLOW:
- return PyLong_Type.tp_as_number->nb_power(
- (PyObject *)v, (PyObject *)w, (PyObject *)z);
- default:
- return NULL;
- }
- }
- return PyInt_FromLong(ix);
-}
-
-static PyObject *
-int_neg(PyIntObject *v)
-{
- register long a;
- a = v->ob_ival;
- /* check for overflow */
- if (UNARY_NEG_WOULD_OVERFLOW(a)) {
- PyObject *o = PyLong_FromLong(a);
- if (o != NULL) {
- PyObject *result = PyNumber_Negative(o);
- Py_DECREF(o);
- return result;
- }
- return NULL;
- }
- return PyInt_FromLong(-a);
-}
-
-static PyObject *
-int_pos(PyIntObject *v)
-{
- if (PyInt_CheckExact(v)) {
- Py_INCREF(v);
- return (PyObject *)v;
- }
- else
- return PyInt_FromLong(v->ob_ival);
-}
-
-static PyObject *
-int_abs(PyIntObject *v)
-{
- if (v->ob_ival >= 0)
- return int_pos(v);
- else
- return int_neg(v);
-}
-
-static int
-int_nonzero(PyIntObject *v)
-{
- return v->ob_ival != 0;
-}
-
-static PyObject *
-int_invert(PyIntObject *v)
-{
- return PyInt_FromLong(~v->ob_ival);
-}
-
-static PyObject *
-int_lshift(PyIntObject *v, PyIntObject *w)
-{
- long a, b, c;
- PyObject *vv, *ww, *result;
-
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- if (b < 0) {
- PyErr_SetString(PyExc_ValueError, "negative shift count");
- return NULL;
- }
- if (a == 0 || b == 0)
- return int_pos(v);
- if (b >= LONG_BIT) {
- vv = PyLong_FromLong(PyInt_AS_LONG(v));
- if (vv == NULL)
- return NULL;
- ww = PyLong_FromLong(PyInt_AS_LONG(w));
- if (ww == NULL) {
- Py_DECREF(vv);
- return NULL;
- }
- result = PyNumber_Lshift(vv, ww);
- Py_DECREF(vv);
- Py_DECREF(ww);
- return result;
- }
- c = a << b;
- if (a != Py_ARITHMETIC_RIGHT_SHIFT(long, c, b)) {
- vv = PyLong_FromLong(PyInt_AS_LONG(v));
- if (vv == NULL)
- return NULL;
- ww = PyLong_FromLong(PyInt_AS_LONG(w));
- if (ww == NULL) {
- Py_DECREF(vv);
- return NULL;
- }
- result = PyNumber_Lshift(vv, ww);
- Py_DECREF(vv);
- Py_DECREF(ww);
- return result;
- }
- return PyInt_FromLong(c);
-}
-
-static PyObject *
-int_rshift(PyIntObject *v, PyIntObject *w)
-{
- register long a, b;
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- if (b < 0) {
- PyErr_SetString(PyExc_ValueError, "negative shift count");
- return NULL;
- }
- if (a == 0 || b == 0)
- return int_pos(v);
- if (b >= LONG_BIT) {
- if (a < 0)
- a = -1;
- else
- a = 0;
- }
- else {
- a = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b);
- }
- return PyInt_FromLong(a);
-}
-
-static PyObject *
-int_and(PyIntObject *v, PyIntObject *w)
-{
- register long a, b;
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- return PyInt_FromLong(a & b);
-}
-
-static PyObject *
-int_xor(PyIntObject *v, PyIntObject *w)
-{
- register long a, b;
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- return PyInt_FromLong(a ^ b);
-}
-
-static PyObject *
-int_or(PyIntObject *v, PyIntObject *w)
-{
- register long a, b;
- CONVERT_TO_LONG(v, a);
- CONVERT_TO_LONG(w, b);
- return PyInt_FromLong(a | b);
-}
-
-static int
-int_coerce(PyObject **pv, PyObject **pw)
-{
- if (PyInt_Check(*pw)) {
- Py_INCREF(*pv);
- Py_INCREF(*pw);
- return 0;
- }
- return 1; /* Can't do it */
-}
-
-static PyObject *
-int_int(PyIntObject *v)
-{
- if (PyInt_CheckExact(v))
- Py_INCREF(v);
- else
- v = (PyIntObject *)PyInt_FromLong(v->ob_ival);
- return (PyObject *)v;
-}
-
-static PyObject *
-int_long(PyIntObject *v)
-{
- return PyLong_FromLong((v -> ob_ival));
-}
-
-static PyObject *
-int_float(PyIntObject *v)
-{
- return PyFloat_FromDouble((double)(v -> ob_ival));
-}
-
-static PyObject *
-int_oct(PyIntObject *v)
-{
- char buf[100];
- long x = v -> ob_ival;
- if (x < 0)
- PyOS_snprintf(buf, sizeof(buf), "-0%lo", -x);
- else if (x == 0)
- strcpy(buf, "0");
- else
- PyOS_snprintf(buf, sizeof(buf), "0%lo", x);
- return PyString_FromString(buf);
-}
-
-static PyObject *
-int_hex(PyIntObject *v)
-{
- char buf[100];
- long x = v -> ob_ival;
- if (x < 0)
- PyOS_snprintf(buf, sizeof(buf), "-0x%lx", -x);
- else
- PyOS_snprintf(buf, sizeof(buf), "0x%lx", x);
- return PyString_FromString(buf);
-}
-
-static PyObject *
-int_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyObject *
-int_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *x = NULL;
- int base = -909;
- static char *kwlist[] = {"x", "base", 0};
-
- if (type != &PyInt_Type)
- return int_subtype_new(type, args, kwds); /* Wimp out */
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist,
- &x, &base))
- return NULL;
- if (x == NULL)
- return PyInt_FromLong(0L);
- if (base == -909)
- return PyNumber_Int(x);
- if (PyString_Check(x)) {
- /* Since PyInt_FromString doesn't have a length parameter,
- * check here for possible NULs in the string. */
- char *string = PyString_AS_STRING(x);
- if (strlen(string) != PyString_Size(x)) {
- /* create a repr() of the input string,
- * just like PyInt_FromString does */
- PyObject *srepr;
- srepr = PyObject_Repr(x);
- if (srepr == NULL)
- return NULL;
- PyErr_Format(PyExc_ValueError,
- "invalid literal for int() with base %d: %s",
- base, PyString_AS_STRING(srepr));
- Py_DECREF(srepr);
- return NULL;
- }
- return PyInt_FromString(string, NULL, base);
- }
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(x))
- return PyInt_FromUnicode(PyUnicode_AS_UNICODE(x),
- PyUnicode_GET_SIZE(x),
- base);
-#endif
- PyErr_SetString(PyExc_TypeError,
- "int() can't convert non-string with explicit base");
- return NULL;
-}
-
-/* Wimpy, slow approach to tp_new calls for subtypes of int:
- first create a regular int from whatever arguments we got,
- then allocate a subtype instance and initialize its ob_ival
- from the regular int. The regular int is then thrown away.
-*/
-static PyObject *
-int_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *tmp, *newobj;
- long ival;
-
- assert(PyType_IsSubtype(type, &PyInt_Type));
- tmp = int_new(&PyInt_Type, args, kwds);
- if (tmp == NULL)
- return NULL;
- if (!PyInt_Check(tmp)) {
- ival = PyLong_AsLong(tmp);
- if (ival == -1 && PyErr_Occurred()) {
- Py_DECREF(tmp);
- return NULL;
- }
- } else {
- ival = ((PyIntObject *)tmp)->ob_ival;
- }
-
- newobj = type->tp_alloc(type, 0);
- if (newobj == NULL) {
- Py_DECREF(tmp);
- return NULL;
- }
- ((PyIntObject *)newobj)->ob_ival = ival;
- Py_DECREF(tmp);
- return newobj;
-}
-
-static PyObject *
-int_getnewargs(PyIntObject *v)
-{
- return Py_BuildValue("(l)", v->ob_ival);
-}
-
-static PyMethodDef int_methods[] = {
- {"__getnewargs__", (PyCFunction)int_getnewargs, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-PyDoc_STRVAR(int_doc,
-"int(x[, base]) -> integer\n\
-\n\
-Convert a string or number to an integer, if possible. A floating point\n\
-argument will be truncated towards zero (this does not include a string\n\
-representation of a floating point number!) When converting a string, use\n\
-the optional base. It is an error to supply a base when converting a\n\
-non-string. If the argument is outside the integer range a long object\n\
-will be returned instead.");
-
-static PyNumberMethods int_as_number = {
- (binaryfunc)int_add, /*nb_add*/
- (binaryfunc)int_sub, /*nb_subtract*/
- (binaryfunc)int_mul, /*nb_multiply*/
- (binaryfunc)int_classic_div, /*nb_divide*/
- (binaryfunc)int_mod, /*nb_remainder*/
- (binaryfunc)int_divmod, /*nb_divmod*/
- (ternaryfunc)int_pow, /*nb_power*/
- (unaryfunc)int_neg, /*nb_negative*/
- (unaryfunc)int_pos, /*nb_positive*/
- (unaryfunc)int_abs, /*nb_absolute*/
- (inquiry)int_nonzero, /*nb_nonzero*/
- (unaryfunc)int_invert, /*nb_invert*/
- (binaryfunc)int_lshift, /*nb_lshift*/
- (binaryfunc)int_rshift, /*nb_rshift*/
- (binaryfunc)int_and, /*nb_and*/
- (binaryfunc)int_xor, /*nb_xor*/
- (binaryfunc)int_or, /*nb_or*/
- int_coerce, /*nb_coerce*/
- (unaryfunc)int_int, /*nb_int*/
- (unaryfunc)int_long, /*nb_long*/
- (unaryfunc)int_float, /*nb_float*/
- (unaryfunc)int_oct, /*nb_oct*/
- (unaryfunc)int_hex, /*nb_hex*/
- 0, /*nb_inplace_add*/
- 0, /*nb_inplace_subtract*/
- 0, /*nb_inplace_multiply*/
- 0, /*nb_inplace_divide*/
- 0, /*nb_inplace_remainder*/
- 0, /*nb_inplace_power*/
- 0, /*nb_inplace_lshift*/
- 0, /*nb_inplace_rshift*/
- 0, /*nb_inplace_and*/
- 0, /*nb_inplace_xor*/
- 0, /*nb_inplace_or*/
- (binaryfunc)int_div, /* nb_floor_divide */
- int_true_divide, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
- (unaryfunc)int_int, /* nb_index */
-};
-
-PyTypeObject PyInt_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "int",
- sizeof(PyIntObject),
- 0,
- (destructor)int_dealloc, /* tp_dealloc */
- (printfunc)int_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)int_compare, /* tp_compare */
- (reprfunc)int_repr, /* tp_repr */
- &int_as_number, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)int_hash, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)int_repr, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- int_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- int_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- int_new, /* tp_new */
- (freefunc)int_free, /* tp_free */
-};
-
-int
-_PyInt_Init(void)
-{
- PyIntObject *v;
- int ival;
-#if NSMALLNEGINTS + NSMALLPOSINTS > 0
- for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) {
- if (!free_list && (free_list = fill_free_list()) == NULL)
- return 0;
- /* PyObject_New is inlined */
- v = free_list;
- free_list = (PyIntObject *)v->ob_type;
- PyObject_INIT(v, &PyInt_Type);
- v->ob_ival = ival;
- small_ints[ival + NSMALLNEGINTS] = v;
- }
-#endif
- return 1;
-}
-
-void
-PyInt_Fini(void)
-{
- PyIntObject *p;
- PyIntBlock *list, *next;
- int i;
- unsigned int ctr;
- int bc, bf; /* block count, number of freed blocks */
- int irem, isum; /* remaining unfreed ints per block, total */
-
-#if NSMALLNEGINTS + NSMALLPOSINTS > 0
- PyIntObject **q;
-
- i = NSMALLNEGINTS + NSMALLPOSINTS;
- q = small_ints;
- while (--i >= 0) {
- Py_XDECREF(*q);
- *q++ = NULL;
- }
-#endif
- bc = 0;
- bf = 0;
- isum = 0;
- list = block_list;
- block_list = NULL;
- free_list = NULL;
- while (list != NULL) {
- bc++;
- irem = 0;
- for (ctr = 0, p = &list->objects[0];
- ctr < N_INTOBJECTS;
- ctr++, p++) {
- if (PyInt_CheckExact(p) && p->ob_refcnt != 0)
- irem++;
- }
- next = list->next;
- if (irem) {
- list->next = block_list;
- block_list = list;
- for (ctr = 0, p = &list->objects[0];
- ctr < N_INTOBJECTS;
- ctr++, p++) {
- if (!PyInt_CheckExact(p) ||
- p->ob_refcnt == 0) {
- p->ob_type = (struct _typeobject *)
- free_list;
- free_list = p;
- }
-#if NSMALLNEGINTS + NSMALLPOSINTS > 0
- else if (-NSMALLNEGINTS <= p->ob_ival &&
- p->ob_ival < NSMALLPOSINTS &&
- small_ints[p->ob_ival +
- NSMALLNEGINTS] == NULL) {
- Py_INCREF(p);
- small_ints[p->ob_ival +
- NSMALLNEGINTS] = p;
- }
-#endif
- }
- }
- else {
- PyMem_FREE(list);
- bf++;
- }
- isum += irem;
- list = next;
- }
- if (!Py_VerboseFlag)
- return;
- fprintf(stderr, "# cleanup ints");
- if (!isum) {
- fprintf(stderr, "\n");
- }
- else {
- fprintf(stderr,
- ": %d unfreed int%s in %d out of %d block%s\n",
- isum, isum == 1 ? "" : "s",
- bc - bf, bc, bc == 1 ? "" : "s");
- }
- if (Py_VerboseFlag > 1) {
- list = block_list;
- while (list != NULL) {
- for (ctr = 0, p = &list->objects[0];
- ctr < N_INTOBJECTS;
- ctr++, p++) {
- if (PyInt_CheckExact(p) && p->ob_refcnt != 0)
- /* XXX(twouters) cast refcount to
- long until %zd is universally
- available
- */
- fprintf(stderr,
- "# <int at %p, refcnt=%ld, val=%ld>\n",
- p, (long)p->ob_refcnt,
- p->ob_ival);
- }
- list = list->next;
- }
- }
-}
diff --git a/sys/src/cmd/python/Objects/iterobject.c b/sys/src/cmd/python/Objects/iterobject.c
deleted file mode 100644
index cf839f478..000000000
--- a/sys/src/cmd/python/Objects/iterobject.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/* Iterator objects */
-
-#include "Python.h"
-
-typedef struct {
- PyObject_HEAD
- long it_index;
- PyObject *it_seq; /* Set to NULL when iterator is exhausted */
-} seqiterobject;
-
-PyObject *
-PySeqIter_New(PyObject *seq)
-{
- seqiterobject *it;
-
- if (!PySequence_Check(seq)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- it = PyObject_GC_New(seqiterobject, &PySeqIter_Type);
- if (it == NULL)
- return NULL;
- it->it_index = 0;
- Py_INCREF(seq);
- it->it_seq = seq;
- _PyObject_GC_TRACK(it);
- return (PyObject *)it;
-}
-
-static void
-iter_dealloc(seqiterobject *it)
-{
- _PyObject_GC_UNTRACK(it);
- Py_XDECREF(it->it_seq);
- PyObject_GC_Del(it);
-}
-
-static int
-iter_traverse(seqiterobject *it, visitproc visit, void *arg)
-{
- Py_VISIT(it->it_seq);
- return 0;
-}
-
-static PyObject *
-iter_iternext(PyObject *iterator)
-{
- seqiterobject *it;
- PyObject *seq;
- PyObject *result;
-
- assert(PySeqIter_Check(iterator));
- it = (seqiterobject *)iterator;
- seq = it->it_seq;
- if (seq == NULL)
- return NULL;
-
- result = PySequence_GetItem(seq, it->it_index);
- if (result != NULL) {
- it->it_index++;
- return result;
- }
- if (PyErr_ExceptionMatches(PyExc_IndexError) ||
- PyErr_ExceptionMatches(PyExc_StopIteration))
- {
- PyErr_Clear();
- Py_DECREF(seq);
- it->it_seq = NULL;
- }
- return NULL;
-}
-
-static PyObject *
-iter_len(seqiterobject *it)
-{
- Py_ssize_t seqsize, len;
-
- if (it->it_seq) {
- seqsize = PySequence_Size(it->it_seq);
- if (seqsize == -1)
- return NULL;
- len = seqsize - it->it_index;
- if (len >= 0)
- return PyInt_FromSsize_t(len);
- }
- return PyInt_FromLong(0);
-}
-
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
-
-static PyMethodDef seqiter_methods[] = {
- {"__length_hint__", (PyCFunction)iter_len, METH_NOARGS, length_hint_doc},
- {NULL, NULL} /* sentinel */
-};
-
-PyTypeObject PySeqIter_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "iterator", /* tp_name */
- sizeof(seqiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)iter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)iter_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- iter_iternext, /* tp_iternext */
- seqiter_methods, /* tp_methods */
- 0, /* tp_members */
-};
-
-/* -------------------------------------- */
-
-typedef struct {
- PyObject_HEAD
- PyObject *it_callable; /* Set to NULL when iterator is exhausted */
- PyObject *it_sentinel; /* Set to NULL when iterator is exhausted */
-} calliterobject;
-
-PyObject *
-PyCallIter_New(PyObject *callable, PyObject *sentinel)
-{
- calliterobject *it;
- it = PyObject_GC_New(calliterobject, &PyCallIter_Type);
- if (it == NULL)
- return NULL;
- Py_INCREF(callable);
- it->it_callable = callable;
- Py_INCREF(sentinel);
- it->it_sentinel = sentinel;
- _PyObject_GC_TRACK(it);
- return (PyObject *)it;
-}
-static void
-calliter_dealloc(calliterobject *it)
-{
- _PyObject_GC_UNTRACK(it);
- Py_XDECREF(it->it_callable);
- Py_XDECREF(it->it_sentinel);
- PyObject_GC_Del(it);
-}
-
-static int
-calliter_traverse(calliterobject *it, visitproc visit, void *arg)
-{
- Py_VISIT(it->it_callable);
- Py_VISIT(it->it_sentinel);
- return 0;
-}
-
-static PyObject *
-calliter_iternext(calliterobject *it)
-{
- if (it->it_callable != NULL) {
- PyObject *args = PyTuple_New(0);
- PyObject *result;
- if (args == NULL)
- return NULL;
- result = PyObject_Call(it->it_callable, args, NULL);
- Py_DECREF(args);
- if (result != NULL) {
- int ok;
- ok = PyObject_RichCompareBool(result,
- it->it_sentinel,
- Py_EQ);
- if (ok == 0)
- return result; /* Common case, fast path */
- Py_DECREF(result);
- if (ok > 0) {
- Py_CLEAR(it->it_callable);
- Py_CLEAR(it->it_sentinel);
- }
- }
- else if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- PyErr_Clear();
- Py_CLEAR(it->it_callable);
- Py_CLEAR(it->it_sentinel);
- }
- }
- return NULL;
-}
-
-PyTypeObject PyCallIter_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "callable-iterator", /* tp_name */
- sizeof(calliterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)calliter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)calliter_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)calliter_iternext, /* tp_iternext */
- 0, /* tp_methods */
-};
diff --git a/sys/src/cmd/python/Objects/listobject.c b/sys/src/cmd/python/Objects/listobject.c
deleted file mode 100644
index 739a571b9..000000000
--- a/sys/src/cmd/python/Objects/listobject.c
+++ /dev/null
@@ -1,2930 +0,0 @@
-/* List object implementation */
-
-#include "Python.h"
-
-#ifdef STDC_HEADERS
-#include <stddef.h>
-#else
-#include <sys/types.h> /* For size_t */
-#endif
-
-/* Ensure ob_item has room for at least newsize elements, and set
- * ob_size to newsize. If newsize > ob_size on entry, the content
- * of the new slots at exit is undefined heap trash; it's the caller's
- * responsiblity to overwrite them with sane values.
- * The number of allocated elements may grow, shrink, or stay the same.
- * Failure is impossible if newsize <= self.allocated on entry, although
- * that partly relies on an assumption that the system realloc() never
- * fails when passed a number of bytes <= the number of bytes last
- * allocated (the C standard doesn't guarantee this, but it's hard to
- * imagine a realloc implementation where it wouldn't be true).
- * Note that self->ob_item may change, and even if newsize is less
- * than ob_size on entry.
- */
-static int
-list_resize(PyListObject *self, Py_ssize_t newsize)
-{
- PyObject **items;
- size_t new_allocated;
- Py_ssize_t allocated = self->allocated;
-
- /* Bypass realloc() when a previous overallocation is large enough
- to accommodate the newsize. If the newsize falls lower than half
- the allocated size, then proceed with the realloc() to shrink the list.
- */
- if (allocated >= newsize && newsize >= (allocated >> 1)) {
- assert(self->ob_item != NULL || newsize == 0);
- self->ob_size = newsize;
- return 0;
- }
-
- /* This over-allocates proportional to the list size, making room
- * for additional growth. The over-allocation is mild, but is
- * enough to give linear-time amortized behavior over a long
- * sequence of appends() in the presence of a poorly-performing
- * system realloc().
- * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
- */
- new_allocated = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;
- if (newsize == 0)
- new_allocated = 0;
- items = self->ob_item;
- if (new_allocated <= ((~(size_t)0) / sizeof(PyObject *)))
- PyMem_RESIZE(items, PyObject *, new_allocated);
- else
- items = NULL;
- if (items == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- self->ob_item = items;
- self->ob_size = newsize;
- self->allocated = new_allocated;
- return 0;
-}
-
-/* Empty list reuse scheme to save calls to malloc and free */
-#define MAXFREELISTS 80
-static PyListObject *free_lists[MAXFREELISTS];
-static int num_free_lists = 0;
-
-void
-PyList_Fini(void)
-{
- PyListObject *op;
-
- while (num_free_lists) {
- num_free_lists--;
- op = free_lists[num_free_lists];
- assert(PyList_CheckExact(op));
- PyObject_GC_Del(op);
- }
-}
-
-PyObject *
-PyList_New(Py_ssize_t size)
-{
- PyListObject *op;
- size_t nbytes;
-
- if (size < 0) {
- PyErr_BadInternalCall();
- return NULL;
- }
- nbytes = size * sizeof(PyObject *);
- /* Check for overflow */
- if (nbytes / sizeof(PyObject *) != (size_t)size)
- return PyErr_NoMemory();
- if (num_free_lists) {
- num_free_lists--;
- op = free_lists[num_free_lists];
- _Py_NewReference((PyObject *)op);
- } else {
- op = PyObject_GC_New(PyListObject, &PyList_Type);
- if (op == NULL)
- return NULL;
- }
- if (size <= 0)
- op->ob_item = NULL;
- else {
- op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
- if (op->ob_item == NULL) {
- Py_DECREF(op);
- return PyErr_NoMemory();
- }
- memset(op->ob_item, 0, nbytes);
- }
- op->ob_size = size;
- op->allocated = size;
- _PyObject_GC_TRACK(op);
- return (PyObject *) op;
-}
-
-Py_ssize_t
-PyList_Size(PyObject *op)
-{
- if (!PyList_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- else
- return ((PyListObject *)op) -> ob_size;
-}
-
-static PyObject *indexerr = NULL;
-
-PyObject *
-PyList_GetItem(PyObject *op, Py_ssize_t i)
-{
- if (!PyList_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- if (i < 0 || i >= ((PyListObject *)op) -> ob_size) {
- if (indexerr == NULL)
- indexerr = PyString_FromString(
- "list index out of range");
- PyErr_SetObject(PyExc_IndexError, indexerr);
- return NULL;
- }
- return ((PyListObject *)op) -> ob_item[i];
-}
-
-int
-PyList_SetItem(register PyObject *op, register Py_ssize_t i,
- register PyObject *newitem)
-{
- register PyObject *olditem;
- register PyObject **p;
- if (!PyList_Check(op)) {
- Py_XDECREF(newitem);
- PyErr_BadInternalCall();
- return -1;
- }
- if (i < 0 || i >= ((PyListObject *)op) -> ob_size) {
- Py_XDECREF(newitem);
- PyErr_SetString(PyExc_IndexError,
- "list assignment index out of range");
- return -1;
- }
- p = ((PyListObject *)op) -> ob_item + i;
- olditem = *p;
- *p = newitem;
- Py_XDECREF(olditem);
- return 0;
-}
-
-static int
-ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
-{
- Py_ssize_t i, n = self->ob_size;
- PyObject **items;
- if (v == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (n == PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "cannot add more objects to list");
- return -1;
- }
-
- if (list_resize(self, n+1) == -1)
- return -1;
-
- if (where < 0) {
- where += n;
- if (where < 0)
- where = 0;
- }
- if (where > n)
- where = n;
- items = self->ob_item;
- for (i = n; --i >= where; )
- items[i+1] = items[i];
- Py_INCREF(v);
- items[where] = v;
- return 0;
-}
-
-int
-PyList_Insert(PyObject *op, Py_ssize_t where, PyObject *newitem)
-{
- if (!PyList_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return ins1((PyListObject *)op, where, newitem);
-}
-
-static int
-app1(PyListObject *self, PyObject *v)
-{
- Py_ssize_t n = PyList_GET_SIZE(self);
-
- assert (v != NULL);
- if (n == PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "cannot add more objects to list");
- return -1;
- }
-
- if (list_resize(self, n+1) == -1)
- return -1;
-
- Py_INCREF(v);
- PyList_SET_ITEM(self, n, v);
- return 0;
-}
-
-int
-PyList_Append(PyObject *op, PyObject *newitem)
-{
- if (PyList_Check(op) && (newitem != NULL))
- return app1((PyListObject *)op, newitem);
- PyErr_BadInternalCall();
- return -1;
-}
-
-/* Methods */
-
-static void
-list_dealloc(PyListObject *op)
-{
- Py_ssize_t i;
- PyObject_GC_UnTrack(op);
- Py_TRASHCAN_SAFE_BEGIN(op)
- if (op->ob_item != NULL) {
- /* Do it backwards, for Christian Tismer.
- There's a simple test case where somehow this reduces
- thrashing when a *very* large list is created and
- immediately deleted. */
- i = op->ob_size;
- while (--i >= 0) {
- Py_XDECREF(op->ob_item[i]);
- }
- PyMem_FREE(op->ob_item);
- }
- if (num_free_lists < MAXFREELISTS && PyList_CheckExact(op))
- free_lists[num_free_lists++] = op;
- else
- op->ob_type->tp_free((PyObject *)op);
- Py_TRASHCAN_SAFE_END(op)
-}
-
-static int
-list_print(PyListObject *op, FILE *fp, int flags)
-{
- int rc;
- Py_ssize_t i;
-
- rc = Py_ReprEnter((PyObject*)op);
- if (rc != 0) {
- if (rc < 0)
- return rc;
- fprintf(fp, "[...]");
- return 0;
- }
- fprintf(fp, "[");
- for (i = 0; i < op->ob_size; i++) {
- if (i > 0)
- fprintf(fp, ", ");
- if (PyObject_Print(op->ob_item[i], fp, 0) != 0) {
- Py_ReprLeave((PyObject *)op);
- return -1;
- }
- }
- fprintf(fp, "]");
- Py_ReprLeave((PyObject *)op);
- return 0;
-}
-
-static PyObject *
-list_repr(PyListObject *v)
-{
- Py_ssize_t i;
- PyObject *s, *temp;
- PyObject *pieces = NULL, *result = NULL;
-
- i = Py_ReprEnter((PyObject*)v);
- if (i != 0) {
- return i > 0 ? PyString_FromString("[...]") : NULL;
- }
-
- if (v->ob_size == 0) {
- result = PyString_FromString("[]");
- goto Done;
- }
-
- pieces = PyList_New(0);
- if (pieces == NULL)
- goto Done;
-
- /* Do repr() on each element. Note that this may mutate the list,
- so must refetch the list size on each iteration. */
- for (i = 0; i < v->ob_size; ++i) {
- int status;
- s = PyObject_Repr(v->ob_item[i]);
- if (s == NULL)
- goto Done;
- status = PyList_Append(pieces, s);
- Py_DECREF(s); /* append created a new ref */
- if (status < 0)
- goto Done;
- }
-
- /* Add "[]" decorations to the first and last items. */
- assert(PyList_GET_SIZE(pieces) > 0);
- s = PyString_FromString("[");
- if (s == NULL)
- goto Done;
- temp = PyList_GET_ITEM(pieces, 0);
- PyString_ConcatAndDel(&s, temp);
- PyList_SET_ITEM(pieces, 0, s);
- if (s == NULL)
- goto Done;
-
- s = PyString_FromString("]");
- if (s == NULL)
- goto Done;
- temp = PyList_GET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1);
- PyString_ConcatAndDel(&temp, s);
- PyList_SET_ITEM(pieces, PyList_GET_SIZE(pieces) - 1, temp);
- if (temp == NULL)
- goto Done;
-
- /* Paste them all together with ", " between. */
- s = PyString_FromString(", ");
- if (s == NULL)
- goto Done;
- result = _PyString_Join(s, pieces);
- Py_DECREF(s);
-
-Done:
- Py_XDECREF(pieces);
- Py_ReprLeave((PyObject *)v);
- return result;
-}
-
-static Py_ssize_t
-list_length(PyListObject *a)
-{
- return a->ob_size;
-}
-
-static int
-list_contains(PyListObject *a, PyObject *el)
-{
- Py_ssize_t i;
- int cmp;
-
- for (i = 0, cmp = 0 ; cmp == 0 && i < a->ob_size; ++i)
- cmp = PyObject_RichCompareBool(el, PyList_GET_ITEM(a, i),
- Py_EQ);
- return cmp;
-}
-
-static PyObject *
-list_item(PyListObject *a, Py_ssize_t i)
-{
- if (i < 0 || i >= a->ob_size) {
- if (indexerr == NULL)
- indexerr = PyString_FromString(
- "list index out of range");
- PyErr_SetObject(PyExc_IndexError, indexerr);
- return NULL;
- }
- Py_INCREF(a->ob_item[i]);
- return a->ob_item[i];
-}
-
-static PyObject *
-list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
-{
- PyListObject *np;
- PyObject **src, **dest;
- Py_ssize_t i, len;
- if (ilow < 0)
- ilow = 0;
- else if (ilow > a->ob_size)
- ilow = a->ob_size;
- if (ihigh < ilow)
- ihigh = ilow;
- else if (ihigh > a->ob_size)
- ihigh = a->ob_size;
- len = ihigh - ilow;
- np = (PyListObject *) PyList_New(len);
- if (np == NULL)
- return NULL;
-
- src = a->ob_item + ilow;
- dest = np->ob_item;
- for (i = 0; i < len; i++) {
- PyObject *v = src[i];
- Py_INCREF(v);
- dest[i] = v;
- }
- return (PyObject *)np;
-}
-
-PyObject *
-PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
-{
- if (!PyList_Check(a)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return list_slice((PyListObject *)a, ilow, ihigh);
-}
-
-static PyObject *
-list_concat(PyListObject *a, PyObject *bb)
-{
- Py_ssize_t size;
- Py_ssize_t i;
- PyObject **src, **dest;
- PyListObject *np;
- if (!PyList_Check(bb)) {
- PyErr_Format(PyExc_TypeError,
- "can only concatenate list (not \"%.200s\") to list",
- bb->ob_type->tp_name);
- return NULL;
- }
-#define b ((PyListObject *)bb)
- size = a->ob_size + b->ob_size;
- if (size < 0)
- return PyErr_NoMemory();
- np = (PyListObject *) PyList_New(size);
- if (np == NULL) {
- return NULL;
- }
- src = a->ob_item;
- dest = np->ob_item;
- for (i = 0; i < a->ob_size; i++) {
- PyObject *v = src[i];
- Py_INCREF(v);
- dest[i] = v;
- }
- src = b->ob_item;
- dest = np->ob_item + a->ob_size;
- for (i = 0; i < b->ob_size; i++) {
- PyObject *v = src[i];
- Py_INCREF(v);
- dest[i] = v;
- }
- return (PyObject *)np;
-#undef b
-}
-
-static PyObject *
-list_repeat(PyListObject *a, Py_ssize_t n)
-{
- Py_ssize_t i, j;
- Py_ssize_t size;
- PyListObject *np;
- PyObject **p, **items;
- PyObject *elem;
- if (n < 0)
- n = 0;
- size = a->ob_size * n;
- if (size == 0)
- return PyList_New(0);
- if (n && size/n != a->ob_size)
- return PyErr_NoMemory();
- np = (PyListObject *) PyList_New(size);
- if (np == NULL)
- return NULL;
-
- items = np->ob_item;
- if (a->ob_size == 1) {
- elem = a->ob_item[0];
- for (i = 0; i < n; i++) {
- items[i] = elem;
- Py_INCREF(elem);
- }
- return (PyObject *) np;
- }
- p = np->ob_item;
- items = a->ob_item;
- for (i = 0; i < n; i++) {
- for (j = 0; j < a->ob_size; j++) {
- *p = items[j];
- Py_INCREF(*p);
- p++;
- }
- }
- return (PyObject *) np;
-}
-
-static int
-list_clear(PyListObject *a)
-{
- Py_ssize_t i;
- PyObject **item = a->ob_item;
- if (item != NULL) {
- /* Because XDECREF can recursively invoke operations on
- this list, we make it empty first. */
- i = a->ob_size;
- a->ob_size = 0;
- a->ob_item = NULL;
- a->allocated = 0;
- while (--i >= 0) {
- Py_XDECREF(item[i]);
- }
- PyMem_FREE(item);
- }
- /* Never fails; the return value can be ignored.
- Note that there is no guarantee that the list is actually empty
- at this point, because XDECREF may have populated it again! */
- return 0;
-}
-
-/* a[ilow:ihigh] = v if v != NULL.
- * del a[ilow:ihigh] if v == NULL.
- *
- * Special speed gimmick: when v is NULL and ihigh - ilow <= 8, it's
- * guaranteed the call cannot fail.
- */
-static int
-list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
-{
- /* Because [X]DECREF can recursively invoke list operations on
- this list, we must postpone all [X]DECREF activity until
- after the list is back in its canonical shape. Therefore
- we must allocate an additional array, 'recycle', into which
- we temporarily copy the items that are deleted from the
- list. :-( */
- PyObject *recycle_on_stack[8];
- PyObject **recycle = recycle_on_stack; /* will allocate more if needed */
- PyObject **item;
- PyObject **vitem = NULL;
- PyObject *v_as_SF = NULL; /* PySequence_Fast(v) */
- Py_ssize_t n; /* # of elements in replacement list */
- Py_ssize_t norig; /* # of elements in list getting replaced */
- Py_ssize_t d; /* Change in size */
- Py_ssize_t k;
- size_t s;
- int result = -1; /* guilty until proved innocent */
-#define b ((PyListObject *)v)
- if (v == NULL)
- n = 0;
- else {
- if (a == b) {
- /* Special case "a[i:j] = a" -- copy b first */
- v = list_slice(b, 0, b->ob_size);
- if (v == NULL)
- return result;
- result = list_ass_slice(a, ilow, ihigh, v);
- Py_DECREF(v);
- return result;
- }
- v_as_SF = PySequence_Fast(v, "can only assign an iterable");
- if(v_as_SF == NULL)
- goto Error;
- n = PySequence_Fast_GET_SIZE(v_as_SF);
- vitem = PySequence_Fast_ITEMS(v_as_SF);
- }
- if (ilow < 0)
- ilow = 0;
- else if (ilow > a->ob_size)
- ilow = a->ob_size;
-
- if (ihigh < ilow)
- ihigh = ilow;
- else if (ihigh > a->ob_size)
- ihigh = a->ob_size;
-
- norig = ihigh - ilow;
- assert(norig >= 0);
- d = n - norig;
- if (a->ob_size + d == 0) {
- Py_XDECREF(v_as_SF);
- return list_clear(a);
- }
- item = a->ob_item;
- /* recycle the items that we are about to remove */
- s = norig * sizeof(PyObject *);
- if (s > sizeof(recycle_on_stack)) {
- recycle = (PyObject **)PyMem_MALLOC(s);
- if (recycle == NULL) {
- PyErr_NoMemory();
- goto Error;
- }
- }
- memcpy(recycle, &item[ilow], s);
-
- if (d < 0) { /* Delete -d items */
- memmove(&item[ihigh+d], &item[ihigh],
- (a->ob_size - ihigh)*sizeof(PyObject *));
- list_resize(a, a->ob_size + d);
- item = a->ob_item;
- }
- else if (d > 0) { /* Insert d items */
- k = a->ob_size;
- if (list_resize(a, k+d) < 0)
- goto Error;
- item = a->ob_item;
- memmove(&item[ihigh+d], &item[ihigh],
- (k - ihigh)*sizeof(PyObject *));
- }
- for (k = 0; k < n; k++, ilow++) {
- PyObject *w = vitem[k];
- Py_XINCREF(w);
- item[ilow] = w;
- }
- for (k = norig - 1; k >= 0; --k)
- Py_XDECREF(recycle[k]);
- result = 0;
- Error:
- if (recycle != recycle_on_stack)
- PyMem_FREE(recycle);
- Py_XDECREF(v_as_SF);
- return result;
-#undef b
-}
-
-int
-PyList_SetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
-{
- if (!PyList_Check(a)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return list_ass_slice((PyListObject *)a, ilow, ihigh, v);
-}
-
-static PyObject *
-list_inplace_repeat(PyListObject *self, Py_ssize_t n)
-{
- PyObject **items;
- Py_ssize_t size, i, j, p;
-
-
- size = PyList_GET_SIZE(self);
- if (size == 0) {
- Py_INCREF(self);
- return (PyObject *)self;
- }
-
- if (n < 1) {
- (void)list_clear(self);
- Py_INCREF(self);
- return (PyObject *)self;
- }
-
- if (list_resize(self, size*n) == -1)
- return NULL;
-
- p = size;
- items = self->ob_item;
- for (i = 1; i < n; i++) { /* Start counting at 1, not 0 */
- for (j = 0; j < size; j++) {
- PyObject *o = items[j];
- Py_INCREF(o);
- items[p++] = o;
- }
- }
- Py_INCREF(self);
- return (PyObject *)self;
-}
-
-static int
-list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v)
-{
- PyObject *old_value;
- if (i < 0 || i >= a->ob_size) {
- PyErr_SetString(PyExc_IndexError,
- "list assignment index out of range");
- return -1;
- }
- if (v == NULL)
- return list_ass_slice(a, i, i+1, v);
- Py_INCREF(v);
- old_value = a->ob_item[i];
- a->ob_item[i] = v;
- Py_DECREF(old_value);
- return 0;
-}
-
-static PyObject *
-listinsert(PyListObject *self, PyObject *args)
-{
- Py_ssize_t i;
- PyObject *v;
- if (!PyArg_ParseTuple(args, "nO:insert", &i, &v))
- return NULL;
- if (ins1(self, i, v) == 0)
- Py_RETURN_NONE;
- return NULL;
-}
-
-static PyObject *
-listappend(PyListObject *self, PyObject *v)
-{
- if (app1(self, v) == 0)
- Py_RETURN_NONE;
- return NULL;
-}
-
-static PyObject *
-listextend(PyListObject *self, PyObject *b)
-{
- PyObject *it; /* iter(v) */
- Py_ssize_t m; /* size of self */
- Py_ssize_t n; /* guess for size of b */
- Py_ssize_t mn; /* m + n */
- Py_ssize_t i;
- PyObject *(*iternext)(PyObject *);
-
- /* Special cases:
- 1) lists and tuples which can use PySequence_Fast ops
- 2) extending self to self requires making a copy first
- */
- if (PyList_CheckExact(b) || PyTuple_CheckExact(b) || (PyObject *)self == b) {
- PyObject **src, **dest;
- b = PySequence_Fast(b, "argument must be iterable");
- if (!b)
- return NULL;
- n = PySequence_Fast_GET_SIZE(b);
- if (n == 0) {
- /* short circuit when b is empty */
- Py_DECREF(b);
- Py_RETURN_NONE;
- }
- m = self->ob_size;
- if (list_resize(self, m + n) == -1) {
- Py_DECREF(b);
- return NULL;
- }
- /* note that we may still have self == b here for the
- * situation a.extend(a), but the following code works
- * in that case too. Just make sure to resize self
- * before calling PySequence_Fast_ITEMS.
- */
- /* populate the end of self with b's items */
- src = PySequence_Fast_ITEMS(b);
- dest = self->ob_item + m;
- for (i = 0; i < n; i++) {
- PyObject *o = src[i];
- Py_INCREF(o);
- dest[i] = o;
- }
- Py_DECREF(b);
- Py_RETURN_NONE;
- }
-
- it = PyObject_GetIter(b);
- if (it == NULL)
- return NULL;
- iternext = *it->ob_type->tp_iternext;
-
- /* Guess a result list size. */
- n = _PyObject_LengthHint(b);
- if (n < 0) {
- if (!PyErr_ExceptionMatches(PyExc_TypeError) &&
- !PyErr_ExceptionMatches(PyExc_AttributeError)) {
- Py_DECREF(it);
- return NULL;
- }
- PyErr_Clear();
- n = 8; /* arbitrary */
- }
- m = self->ob_size;
- mn = m + n;
- if (mn >= m) {
- /* Make room. */
- if (list_resize(self, mn) == -1)
- goto error;
- /* Make the list sane again. */
- self->ob_size = m;
- }
- /* Else m + n overflowed; on the chance that n lied, and there really
- * is enough room, ignore it. If n was telling the truth, we'll
- * eventually run out of memory during the loop.
- */
-
- /* Run iterator to exhaustion. */
- for (;;) {
- PyObject *item = iternext(it);
- if (item == NULL) {
- if (PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_StopIteration))
- PyErr_Clear();
- else
- goto error;
- }
- break;
- }
- if (self->ob_size < self->allocated) {
- /* steals ref */
- PyList_SET_ITEM(self, self->ob_size, item);
- ++self->ob_size;
- }
- else {
- int status = app1(self, item);
- Py_DECREF(item); /* append creates a new ref */
- if (status < 0)
- goto error;
- }
- }
-
- /* Cut back result list if initial guess was too large. */
- if (self->ob_size < self->allocated)
- list_resize(self, self->ob_size); /* shrinking can't fail */
-
- Py_DECREF(it);
- Py_RETURN_NONE;
-
- error:
- Py_DECREF(it);
- return NULL;
-}
-
-PyObject *
-_PyList_Extend(PyListObject *self, PyObject *b)
-{
- return listextend(self, b);
-}
-
-static PyObject *
-list_inplace_concat(PyListObject *self, PyObject *other)
-{
- PyObject *result;
-
- result = listextend(self, other);
- if (result == NULL)
- return result;
- Py_DECREF(result);
- Py_INCREF(self);
- return (PyObject *)self;
-}
-
-static PyObject *
-listpop(PyListObject *self, PyObject *args)
-{
- Py_ssize_t i = -1;
- PyObject *v;
- int status;
-
- if (!PyArg_ParseTuple(args, "|n:pop", &i))
- return NULL;
-
- if (self->ob_size == 0) {
- /* Special-case most common failure cause */
- PyErr_SetString(PyExc_IndexError, "pop from empty list");
- return NULL;
- }
- if (i < 0)
- i += self->ob_size;
- if (i < 0 || i >= self->ob_size) {
- PyErr_SetString(PyExc_IndexError, "pop index out of range");
- return NULL;
- }
- v = self->ob_item[i];
- if (i == self->ob_size - 1) {
- status = list_resize(self, self->ob_size - 1);
- assert(status >= 0);
- return v; /* and v now owns the reference the list had */
- }
- Py_INCREF(v);
- status = list_ass_slice(self, i, i+1, (PyObject *)NULL);
- assert(status >= 0);
- /* Use status, so that in a release build compilers don't
- * complain about the unused name.
- */
- (void) status;
-
- return v;
-}
-
-/* Reverse a slice of a list in place, from lo up to (exclusive) hi. */
-static void
-reverse_slice(PyObject **lo, PyObject **hi)
-{
- assert(lo && hi);
-
- --hi;
- while (lo < hi) {
- PyObject *t = *lo;
- *lo = *hi;
- *hi = t;
- ++lo;
- --hi;
- }
-}
-
-/* Lots of code for an adaptive, stable, natural mergesort. There are many
- * pieces to this algorithm; read listsort.txt for overviews and details.
- */
-
-/* Comparison function. Takes care of calling a user-supplied
- * comparison function (any callable Python object), which must not be
- * NULL (use the ISLT macro if you don't know, or call PyObject_RichCompareBool
- * with Py_LT if you know it's NULL).
- * Returns -1 on error, 1 if x < y, 0 if x >= y.
- */
-static int
-islt(PyObject *x, PyObject *y, PyObject *compare)
-{
- PyObject *res;
- PyObject *args;
- Py_ssize_t i;
-
- assert(compare != NULL);
- /* Call the user's comparison function and translate the 3-way
- * result into true or false (or error).
- */
- args = PyTuple_New(2);
- if (args == NULL)
- return -1;
- Py_INCREF(x);
- Py_INCREF(y);
- PyTuple_SET_ITEM(args, 0, x);
- PyTuple_SET_ITEM(args, 1, y);
- res = PyObject_Call(compare, args, NULL);
- Py_DECREF(args);
- if (res == NULL)
- return -1;
- if (!PyInt_Check(res)) {
- Py_DECREF(res);
- PyErr_SetString(PyExc_TypeError,
- "comparison function must return int");
- return -1;
- }
- i = PyInt_AsLong(res);
- Py_DECREF(res);
- return i < 0;
-}
-
-/* If COMPARE is NULL, calls PyObject_RichCompareBool with Py_LT, else calls
- * islt. This avoids a layer of function call in the usual case, and
- * sorting does many comparisons.
- * Returns -1 on error, 1 if x < y, 0 if x >= y.
- */
-#define ISLT(X, Y, COMPARE) ((COMPARE) == NULL ? \
- PyObject_RichCompareBool(X, Y, Py_LT) : \
- islt(X, Y, COMPARE))
-
-/* Compare X to Y via "<". Goto "fail" if the comparison raises an
- error. Else "k" is set to true iff X<Y, and an "if (k)" block is
- started. It makes more sense in context <wink>. X and Y are PyObject*s.
-*/
-#define IFLT(X, Y) if ((k = ISLT(X, Y, compare)) < 0) goto fail; \
- if (k)
-
-/* binarysort is the best method for sorting small arrays: it does
- few compares, but can do data movement quadratic in the number of
- elements.
- [lo, hi) is a contiguous slice of a list, and is sorted via
- binary insertion. This sort is stable.
- On entry, must have lo <= start <= hi, and that [lo, start) is already
- sorted (pass start == lo if you don't know!).
- If islt() complains return -1, else 0.
- Even in case of error, the output slice will be some permutation of
- the input (nothing is lost or duplicated).
-*/
-static int
-binarysort(PyObject **lo, PyObject **hi, PyObject **start, PyObject *compare)
- /* compare -- comparison function object, or NULL for default */
-{
- register Py_ssize_t k;
- register PyObject **l, **p, **r;
- register PyObject *pivot;
-
- assert(lo <= start && start <= hi);
- /* assert [lo, start) is sorted */
- if (lo == start)
- ++start;
- for (; start < hi; ++start) {
- /* set l to where *start belongs */
- l = lo;
- r = start;
- pivot = *r;
- /* Invariants:
- * pivot >= all in [lo, l).
- * pivot < all in [r, start).
- * The second is vacuously true at the start.
- */
- assert(l < r);
- do {
- p = l + ((r - l) >> 1);
- IFLT(pivot, *p)
- r = p;
- else
- l = p+1;
- } while (l < r);
- assert(l == r);
- /* The invariants still hold, so pivot >= all in [lo, l) and
- pivot < all in [l, start), so pivot belongs at l. Note
- that if there are elements equal to pivot, l points to the
- first slot after them -- that's why this sort is stable.
- Slide over to make room.
- Caution: using memmove is much slower under MSVC 5;
- we're not usually moving many slots. */
- for (p = start; p > l; --p)
- *p = *(p-1);
- *l = pivot;
- }
- return 0;
-
- fail:
- return -1;
-}
-
-/*
-Return the length of the run beginning at lo, in the slice [lo, hi). lo < hi
-is required on entry. "A run" is the longest ascending sequence, with
-
- lo[0] <= lo[1] <= lo[2] <= ...
-
-or the longest descending sequence, with
-
- lo[0] > lo[1] > lo[2] > ...
-
-Boolean *descending is set to 0 in the former case, or to 1 in the latter.
-For its intended use in a stable mergesort, the strictness of the defn of
-"descending" is needed so that the caller can safely reverse a descending
-sequence without violating stability (strict > ensures there are no equal
-elements to get out of order).
-
-Returns -1 in case of error.
-*/
-static Py_ssize_t
-count_run(PyObject **lo, PyObject **hi, PyObject *compare, int *descending)
-{
- Py_ssize_t k;
- Py_ssize_t n;
-
- assert(lo < hi);
- *descending = 0;
- ++lo;
- if (lo == hi)
- return 1;
-
- n = 2;
- IFLT(*lo, *(lo-1)) {
- *descending = 1;
- for (lo = lo+1; lo < hi; ++lo, ++n) {
- IFLT(*lo, *(lo-1))
- ;
- else
- break;
- }
- }
- else {
- for (lo = lo+1; lo < hi; ++lo, ++n) {
- IFLT(*lo, *(lo-1))
- break;
- }
- }
-
- return n;
-fail:
- return -1;
-}
-
-/*
-Locate the proper position of key in a sorted vector; if the vector contains
-an element equal to key, return the position immediately to the left of
-the leftmost equal element. [gallop_right() does the same except returns
-the position to the right of the rightmost equal element (if any).]
-
-"a" is a sorted vector with n elements, starting at a[0]. n must be > 0.
-
-"hint" is an index at which to begin the search, 0 <= hint < n. The closer
-hint is to the final result, the faster this runs.
-
-The return value is the int k in 0..n such that
-
- a[k-1] < key <= a[k]
-
-pretending that *(a-1) is minus infinity and a[n] is plus infinity. IOW,
-key belongs at index k; or, IOW, the first k elements of a should precede
-key, and the last n-k should follow key.
-
-Returns -1 on error. See listsort.txt for info on the method.
-*/
-static Py_ssize_t
-gallop_left(PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize_t hint, PyObject *compare)
-{
- Py_ssize_t ofs;
- Py_ssize_t lastofs;
- Py_ssize_t k;
-
- assert(key && a && n > 0 && hint >= 0 && hint < n);
-
- a += hint;
- lastofs = 0;
- ofs = 1;
- IFLT(*a, key) {
- /* a[hint] < key -- gallop right, until
- * a[hint + lastofs] < key <= a[hint + ofs]
- */
- const Py_ssize_t maxofs = n - hint; /* &a[n-1] is highest */
- while (ofs < maxofs) {
- IFLT(a[ofs], key) {
- lastofs = ofs;
- ofs = (ofs << 1) + 1;
- if (ofs <= 0) /* int overflow */
- ofs = maxofs;
- }
- else /* key <= a[hint + ofs] */
- break;
- }
- if (ofs > maxofs)
- ofs = maxofs;
- /* Translate back to offsets relative to &a[0]. */
- lastofs += hint;
- ofs += hint;
- }
- else {
- /* key <= a[hint] -- gallop left, until
- * a[hint - ofs] < key <= a[hint - lastofs]
- */
- const Py_ssize_t maxofs = hint + 1; /* &a[0] is lowest */
- while (ofs < maxofs) {
- IFLT(*(a-ofs), key)
- break;
- /* key <= a[hint - ofs] */
- lastofs = ofs;
- ofs = (ofs << 1) + 1;
- if (ofs <= 0) /* int overflow */
- ofs = maxofs;
- }
- if (ofs > maxofs)
- ofs = maxofs;
- /* Translate back to positive offsets relative to &a[0]. */
- k = lastofs;
- lastofs = hint - ofs;
- ofs = hint - k;
- }
- a -= hint;
-
- assert(-1 <= lastofs && lastofs < ofs && ofs <= n);
- /* Now a[lastofs] < key <= a[ofs], so key belongs somewhere to the
- * right of lastofs but no farther right than ofs. Do a binary
- * search, with invariant a[lastofs-1] < key <= a[ofs].
- */
- ++lastofs;
- while (lastofs < ofs) {
- Py_ssize_t m = lastofs + ((ofs - lastofs) >> 1);
-
- IFLT(a[m], key)
- lastofs = m+1; /* a[m] < key */
- else
- ofs = m; /* key <= a[m] */
- }
- assert(lastofs == ofs); /* so a[ofs-1] < key <= a[ofs] */
- return ofs;
-
-fail:
- return -1;
-}
-
-/*
-Exactly like gallop_left(), except that if key already exists in a[0:n],
-finds the position immediately to the right of the rightmost equal value.
-
-The return value is the int k in 0..n such that
-
- a[k-1] <= key < a[k]
-
-or -1 if error.
-
-The code duplication is massive, but this is enough different given that
-we're sticking to "<" comparisons that it's much harder to follow if
-written as one routine with yet another "left or right?" flag.
-*/
-static Py_ssize_t
-gallop_right(PyObject *key, PyObject **a, Py_ssize_t n, Py_ssize_t hint, PyObject *compare)
-{
- Py_ssize_t ofs;
- Py_ssize_t lastofs;
- Py_ssize_t k;
-
- assert(key && a && n > 0 && hint >= 0 && hint < n);
-
- a += hint;
- lastofs = 0;
- ofs = 1;
- IFLT(key, *a) {
- /* key < a[hint] -- gallop left, until
- * a[hint - ofs] <= key < a[hint - lastofs]
- */
- const Py_ssize_t maxofs = hint + 1; /* &a[0] is lowest */
- while (ofs < maxofs) {
- IFLT(key, *(a-ofs)) {
- lastofs = ofs;
- ofs = (ofs << 1) + 1;
- if (ofs <= 0) /* int overflow */
- ofs = maxofs;
- }
- else /* a[hint - ofs] <= key */
- break;
- }
- if (ofs > maxofs)
- ofs = maxofs;
- /* Translate back to positive offsets relative to &a[0]. */
- k = lastofs;
- lastofs = hint - ofs;
- ofs = hint - k;
- }
- else {
- /* a[hint] <= key -- gallop right, until
- * a[hint + lastofs] <= key < a[hint + ofs]
- */
- const Py_ssize_t maxofs = n - hint; /* &a[n-1] is highest */
- while (ofs < maxofs) {
- IFLT(key, a[ofs])
- break;
- /* a[hint + ofs] <= key */
- lastofs = ofs;
- ofs = (ofs << 1) + 1;
- if (ofs <= 0) /* int overflow */
- ofs = maxofs;
- }
- if (ofs > maxofs)
- ofs = maxofs;
- /* Translate back to offsets relative to &a[0]. */
- lastofs += hint;
- ofs += hint;
- }
- a -= hint;
-
- assert(-1 <= lastofs && lastofs < ofs && ofs <= n);
- /* Now a[lastofs] <= key < a[ofs], so key belongs somewhere to the
- * right of lastofs but no farther right than ofs. Do a binary
- * search, with invariant a[lastofs-1] <= key < a[ofs].
- */
- ++lastofs;
- while (lastofs < ofs) {
- Py_ssize_t m = lastofs + ((ofs - lastofs) >> 1);
-
- IFLT(key, a[m])
- ofs = m; /* key < a[m] */
- else
- lastofs = m+1; /* a[m] <= key */
- }
- assert(lastofs == ofs); /* so a[ofs-1] <= key < a[ofs] */
- return ofs;
-
-fail:
- return -1;
-}
-
-/* The maximum number of entries in a MergeState's pending-runs stack.
- * This is enough to sort arrays of size up to about
- * 32 * phi ** MAX_MERGE_PENDING
- * where phi ~= 1.618. 85 is ridiculouslylarge enough, good for an array
- * with 2**64 elements.
- */
-#define MAX_MERGE_PENDING 85
-
-/* When we get into galloping mode, we stay there until both runs win less
- * often than MIN_GALLOP consecutive times. See listsort.txt for more info.
- */
-#define MIN_GALLOP 7
-
-/* Avoid malloc for small temp arrays. */
-#define MERGESTATE_TEMP_SIZE 256
-
-/* One MergeState exists on the stack per invocation of mergesort. It's just
- * a convenient way to pass state around among the helper functions.
- */
-struct s_slice {
- PyObject **base;
- Py_ssize_t len;
-};
-
-typedef struct s_MergeState {
- /* The user-supplied comparison function. or NULL if none given. */
- PyObject *compare;
-
- /* This controls when we get *into* galloping mode. It's initialized
- * to MIN_GALLOP. merge_lo and merge_hi tend to nudge it higher for
- * random data, and lower for highly structured data.
- */
- Py_ssize_t min_gallop;
-
- /* 'a' is temp storage to help with merges. It contains room for
- * alloced entries.
- */
- PyObject **a; /* may point to temparray below */
- Py_ssize_t alloced;
-
- /* A stack of n pending runs yet to be merged. Run #i starts at
- * address base[i] and extends for len[i] elements. It's always
- * true (so long as the indices are in bounds) that
- *
- * pending[i].base + pending[i].len == pending[i+1].base
- *
- * so we could cut the storage for this, but it's a minor amount,
- * and keeping all the info explicit simplifies the code.
- */
- int n;
- struct s_slice pending[MAX_MERGE_PENDING];
-
- /* 'a' points to this when possible, rather than muck with malloc. */
- PyObject *temparray[MERGESTATE_TEMP_SIZE];
-} MergeState;
-
-/* Conceptually a MergeState's constructor. */
-static void
-merge_init(MergeState *ms, PyObject *compare)
-{
- assert(ms != NULL);
- ms->compare = compare;
- ms->a = ms->temparray;
- ms->alloced = MERGESTATE_TEMP_SIZE;
- ms->n = 0;
- ms->min_gallop = MIN_GALLOP;
-}
-
-/* Free all the temp memory owned by the MergeState. This must be called
- * when you're done with a MergeState, and may be called before then if
- * you want to free the temp memory early.
- */
-static void
-merge_freemem(MergeState *ms)
-{
- assert(ms != NULL);
- if (ms->a != ms->temparray)
- PyMem_Free(ms->a);
- ms->a = ms->temparray;
- ms->alloced = MERGESTATE_TEMP_SIZE;
-}
-
-/* Ensure enough temp memory for 'need' array slots is available.
- * Returns 0 on success and -1 if the memory can't be gotten.
- */
-static int
-merge_getmem(MergeState *ms, Py_ssize_t need)
-{
- assert(ms != NULL);
- if (need <= ms->alloced)
- return 0;
- /* Don't realloc! That can cost cycles to copy the old data, but
- * we don't care what's in the block.
- */
- merge_freemem(ms);
- ms->a = (PyObject **)PyMem_Malloc(need * sizeof(PyObject*));
- if (ms->a) {
- ms->alloced = need;
- return 0;
- }
- PyErr_NoMemory();
- merge_freemem(ms); /* reset to sane state */
- return -1;
-}
-#define MERGE_GETMEM(MS, NEED) ((NEED) <= (MS)->alloced ? 0 : \
- merge_getmem(MS, NEED))
-
-/* Merge the na elements starting at pa with the nb elements starting at pb
- * in a stable way, in-place. na and nb must be > 0, and pa + na == pb.
- * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the
- * merge, and should have na <= nb. See listsort.txt for more info.
- * Return 0 if successful, -1 if error.
- */
-static Py_ssize_t
-merge_lo(MergeState *ms, PyObject **pa, Py_ssize_t na,
- PyObject **pb, Py_ssize_t nb)
-{
- Py_ssize_t k;
- PyObject *compare;
- PyObject **dest;
- int result = -1; /* guilty until proved innocent */
- Py_ssize_t min_gallop = ms->min_gallop;
-
- assert(ms && pa && pb && na > 0 && nb > 0 && pa + na == pb);
- if (MERGE_GETMEM(ms, na) < 0)
- return -1;
- memcpy(ms->a, pa, na * sizeof(PyObject*));
- dest = pa;
- pa = ms->a;
-
- *dest++ = *pb++;
- --nb;
- if (nb == 0)
- goto Succeed;
- if (na == 1)
- goto CopyB;
-
- compare = ms->compare;
- for (;;) {
- Py_ssize_t acount = 0; /* # of times A won in a row */
- Py_ssize_t bcount = 0; /* # of times B won in a row */
-
- /* Do the straightforward thing until (if ever) one run
- * appears to win consistently.
- */
- for (;;) {
- assert(na > 1 && nb > 0);
- k = ISLT(*pb, *pa, compare);
- if (k) {
- if (k < 0)
- goto Fail;
- *dest++ = *pb++;
- ++bcount;
- acount = 0;
- --nb;
- if (nb == 0)
- goto Succeed;
- if (bcount >= min_gallop)
- break;
- }
- else {
- *dest++ = *pa++;
- ++acount;
- bcount = 0;
- --na;
- if (na == 1)
- goto CopyB;
- if (acount >= min_gallop)
- break;
- }
- }
-
- /* One run is winning so consistently that galloping may
- * be a huge win. So try that, and continue galloping until
- * (if ever) neither run appears to be winning consistently
- * anymore.
- */
- ++min_gallop;
- do {
- assert(na > 1 && nb > 0);
- min_gallop -= min_gallop > 1;
- ms->min_gallop = min_gallop;
- k = gallop_right(*pb, pa, na, 0, compare);
- acount = k;
- if (k) {
- if (k < 0)
- goto Fail;
- memcpy(dest, pa, k * sizeof(PyObject *));
- dest += k;
- pa += k;
- na -= k;
- if (na == 1)
- goto CopyB;
- /* na==0 is impossible now if the comparison
- * function is consistent, but we can't assume
- * that it is.
- */
- if (na == 0)
- goto Succeed;
- }
- *dest++ = *pb++;
- --nb;
- if (nb == 0)
- goto Succeed;
-
- k = gallop_left(*pa, pb, nb, 0, compare);
- bcount = k;
- if (k) {
- if (k < 0)
- goto Fail;
- memmove(dest, pb, k * sizeof(PyObject *));
- dest += k;
- pb += k;
- nb -= k;
- if (nb == 0)
- goto Succeed;
- }
- *dest++ = *pa++;
- --na;
- if (na == 1)
- goto CopyB;
- } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);
- ++min_gallop; /* penalize it for leaving galloping mode */
- ms->min_gallop = min_gallop;
- }
-Succeed:
- result = 0;
-Fail:
- if (na)
- memcpy(dest, pa, na * sizeof(PyObject*));
- return result;
-CopyB:
- assert(na == 1 && nb > 0);
- /* The last element of pa belongs at the end of the merge. */
- memmove(dest, pb, nb * sizeof(PyObject *));
- dest[nb] = *pa;
- return 0;
-}
-
-/* Merge the na elements starting at pa with the nb elements starting at pb
- * in a stable way, in-place. na and nb must be > 0, and pa + na == pb.
- * Must also have that *pb < *pa, that pa[na-1] belongs at the end of the
- * merge, and should have na >= nb. See listsort.txt for more info.
- * Return 0 if successful, -1 if error.
- */
-static Py_ssize_t
-merge_hi(MergeState *ms, PyObject **pa, Py_ssize_t na, PyObject **pb, Py_ssize_t nb)
-{
- Py_ssize_t k;
- PyObject *compare;
- PyObject **dest;
- int result = -1; /* guilty until proved innocent */
- PyObject **basea;
- PyObject **baseb;
- Py_ssize_t min_gallop = ms->min_gallop;
-
- assert(ms && pa && pb && na > 0 && nb > 0 && pa + na == pb);
- if (MERGE_GETMEM(ms, nb) < 0)
- return -1;
- dest = pb + nb - 1;
- memcpy(ms->a, pb, nb * sizeof(PyObject*));
- basea = pa;
- baseb = ms->a;
- pb = ms->a + nb - 1;
- pa += na - 1;
-
- *dest-- = *pa--;
- --na;
- if (na == 0)
- goto Succeed;
- if (nb == 1)
- goto CopyA;
-
- compare = ms->compare;
- for (;;) {
- Py_ssize_t acount = 0; /* # of times A won in a row */
- Py_ssize_t bcount = 0; /* # of times B won in a row */
-
- /* Do the straightforward thing until (if ever) one run
- * appears to win consistently.
- */
- for (;;) {
- assert(na > 0 && nb > 1);
- k = ISLT(*pb, *pa, compare);
- if (k) {
- if (k < 0)
- goto Fail;
- *dest-- = *pa--;
- ++acount;
- bcount = 0;
- --na;
- if (na == 0)
- goto Succeed;
- if (acount >= min_gallop)
- break;
- }
- else {
- *dest-- = *pb--;
- ++bcount;
- acount = 0;
- --nb;
- if (nb == 1)
- goto CopyA;
- if (bcount >= min_gallop)
- break;
- }
- }
-
- /* One run is winning so consistently that galloping may
- * be a huge win. So try that, and continue galloping until
- * (if ever) neither run appears to be winning consistently
- * anymore.
- */
- ++min_gallop;
- do {
- assert(na > 0 && nb > 1);
- min_gallop -= min_gallop > 1;
- ms->min_gallop = min_gallop;
- k = gallop_right(*pb, basea, na, na-1, compare);
- if (k < 0)
- goto Fail;
- k = na - k;
- acount = k;
- if (k) {
- dest -= k;
- pa -= k;
- memmove(dest+1, pa+1, k * sizeof(PyObject *));
- na -= k;
- if (na == 0)
- goto Succeed;
- }
- *dest-- = *pb--;
- --nb;
- if (nb == 1)
- goto CopyA;
-
- k = gallop_left(*pa, baseb, nb, nb-1, compare);
- if (k < 0)
- goto Fail;
- k = nb - k;
- bcount = k;
- if (k) {
- dest -= k;
- pb -= k;
- memcpy(dest+1, pb+1, k * sizeof(PyObject *));
- nb -= k;
- if (nb == 1)
- goto CopyA;
- /* nb==0 is impossible now if the comparison
- * function is consistent, but we can't assume
- * that it is.
- */
- if (nb == 0)
- goto Succeed;
- }
- *dest-- = *pa--;
- --na;
- if (na == 0)
- goto Succeed;
- } while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);
- ++min_gallop; /* penalize it for leaving galloping mode */
- ms->min_gallop = min_gallop;
- }
-Succeed:
- result = 0;
-Fail:
- if (nb)
- memcpy(dest-(nb-1), baseb, nb * sizeof(PyObject*));
- return result;
-CopyA:
- assert(nb == 1 && na > 0);
- /* The first element of pb belongs at the front of the merge. */
- dest -= na;
- pa -= na;
- memmove(dest+1, pa+1, na * sizeof(PyObject *));
- *dest = *pb;
- return 0;
-}
-
-/* Merge the two runs at stack indices i and i+1.
- * Returns 0 on success, -1 on error.
- */
-static Py_ssize_t
-merge_at(MergeState *ms, Py_ssize_t i)
-{
- PyObject **pa, **pb;
- Py_ssize_t na, nb;
- Py_ssize_t k;
- PyObject *compare;
-
- assert(ms != NULL);
- assert(ms->n >= 2);
- assert(i >= 0);
- assert(i == ms->n - 2 || i == ms->n - 3);
-
- pa = ms->pending[i].base;
- na = ms->pending[i].len;
- pb = ms->pending[i+1].base;
- nb = ms->pending[i+1].len;
- assert(na > 0 && nb > 0);
- assert(pa + na == pb);
-
- /* Record the length of the combined runs; if i is the 3rd-last
- * run now, also slide over the last run (which isn't involved
- * in this merge). The current run i+1 goes away in any case.
- */
- ms->pending[i].len = na + nb;
- if (i == ms->n - 3)
- ms->pending[i+1] = ms->pending[i+2];
- --ms->n;
-
- /* Where does b start in a? Elements in a before that can be
- * ignored (already in place).
- */
- compare = ms->compare;
- k = gallop_right(*pb, pa, na, 0, compare);
- if (k < 0)
- return -1;
- pa += k;
- na -= k;
- if (na == 0)
- return 0;
-
- /* Where does a end in b? Elements in b after that can be
- * ignored (already in place).
- */
- nb = gallop_left(pa[na-1], pb, nb, nb-1, compare);
- if (nb <= 0)
- return nb;
-
- /* Merge what remains of the runs, using a temp array with
- * min(na, nb) elements.
- */
- if (na <= nb)
- return merge_lo(ms, pa, na, pb, nb);
- else
- return merge_hi(ms, pa, na, pb, nb);
-}
-
-/* Examine the stack of runs waiting to be merged, merging adjacent runs
- * until the stack invariants are re-established:
- *
- * 1. len[-3] > len[-2] + len[-1]
- * 2. len[-2] > len[-1]
- *
- * See listsort.txt for more info.
- *
- * Returns 0 on success, -1 on error.
- */
-static int
-merge_collapse(MergeState *ms)
-{
- struct s_slice *p = ms->pending;
-
- assert(ms);
- while (ms->n > 1) {
- Py_ssize_t n = ms->n - 2;
- if (n > 0 && p[n-1].len <= p[n].len + p[n+1].len) {
- if (p[n-1].len < p[n+1].len)
- --n;
- if (merge_at(ms, n) < 0)
- return -1;
- }
- else if (p[n].len <= p[n+1].len) {
- if (merge_at(ms, n) < 0)
- return -1;
- }
- else
- break;
- }
- return 0;
-}
-
-/* Regardless of invariants, merge all runs on the stack until only one
- * remains. This is used at the end of the mergesort.
- *
- * Returns 0 on success, -1 on error.
- */
-static int
-merge_force_collapse(MergeState *ms)
-{
- struct s_slice *p = ms->pending;
-
- assert(ms);
- while (ms->n > 1) {
- Py_ssize_t n = ms->n - 2;
- if (n > 0 && p[n-1].len < p[n+1].len)
- --n;
- if (merge_at(ms, n) < 0)
- return -1;
- }
- return 0;
-}
-
-/* Compute a good value for the minimum run length; natural runs shorter
- * than this are boosted artificially via binary insertion.
- *
- * If n < 64, return n (it's too small to bother with fancy stuff).
- * Else if n is an exact power of 2, return 32.
- * Else return an int k, 32 <= k <= 64, such that n/k is close to, but
- * strictly less than, an exact power of 2.
- *
- * See listsort.txt for more info.
- */
-static Py_ssize_t
-merge_compute_minrun(Py_ssize_t n)
-{
- Py_ssize_t r = 0; /* becomes 1 if any 1 bits are shifted off */
-
- assert(n >= 0);
- while (n >= 64) {
- r |= n & 1;
- n >>= 1;
- }
- return n + r;
-}
-
-/* Special wrapper to support stable sorting using the decorate-sort-undecorate
- pattern. Holds a key which is used for comparisons and the original record
- which is returned during the undecorate phase. By exposing only the key
- during comparisons, the underlying sort stability characteristics are left
- unchanged. Also, if a custom comparison function is used, it will only see
- the key instead of a full record. */
-
-typedef struct {
- PyObject_HEAD
- PyObject *key;
- PyObject *value;
-} sortwrapperobject;
-
-PyDoc_STRVAR(sortwrapper_doc, "Object wrapper with a custom sort key.");
-static PyObject *
-sortwrapper_richcompare(sortwrapperobject *, sortwrapperobject *, int);
-static void
-sortwrapper_dealloc(sortwrapperobject *);
-
-static PyTypeObject sortwrapper_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "sortwrapper", /* tp_name */
- sizeof(sortwrapperobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)sortwrapper_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT |
- Py_TPFLAGS_HAVE_RICHCOMPARE, /* tp_flags */
- sortwrapper_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- (richcmpfunc)sortwrapper_richcompare, /* tp_richcompare */
-};
-
-
-static PyObject *
-sortwrapper_richcompare(sortwrapperobject *a, sortwrapperobject *b, int op)
-{
- if (!PyObject_TypeCheck(b, &sortwrapper_type)) {
- PyErr_SetString(PyExc_TypeError,
- "expected a sortwrapperobject");
- return NULL;
- }
- return PyObject_RichCompare(a->key, b->key, op);
-}
-
-static void
-sortwrapper_dealloc(sortwrapperobject *so)
-{
- Py_XDECREF(so->key);
- Py_XDECREF(so->value);
- PyObject_Del(so);
-}
-
-/* Returns a new reference to a sortwrapper.
- Consumes the references to the two underlying objects. */
-
-static PyObject *
-build_sortwrapper(PyObject *key, PyObject *value)
-{
- sortwrapperobject *so;
-
- so = PyObject_New(sortwrapperobject, &sortwrapper_type);
- if (so == NULL)
- return NULL;
- so->key = key;
- so->value = value;
- return (PyObject *)so;
-}
-
-/* Returns a new reference to the value underlying the wrapper. */
-static PyObject *
-sortwrapper_getvalue(PyObject *so)
-{
- PyObject *value;
-
- if (!PyObject_TypeCheck(so, &sortwrapper_type)) {
- PyErr_SetString(PyExc_TypeError,
- "expected a sortwrapperobject");
- return NULL;
- }
- value = ((sortwrapperobject *)so)->value;
- Py_INCREF(value);
- return value;
-}
-
-/* Wrapper for user specified cmp functions in combination with a
- specified key function. Makes sure the cmp function is presented
- with the actual key instead of the sortwrapper */
-
-typedef struct {
- PyObject_HEAD
- PyObject *func;
-} cmpwrapperobject;
-
-static void
-cmpwrapper_dealloc(cmpwrapperobject *co)
-{
- Py_XDECREF(co->func);
- PyObject_Del(co);
-}
-
-static PyObject *
-cmpwrapper_call(cmpwrapperobject *co, PyObject *args, PyObject *kwds)
-{
- PyObject *x, *y, *xx, *yy;
-
- if (!PyArg_UnpackTuple(args, "", 2, 2, &x, &y))
- return NULL;
- if (!PyObject_TypeCheck(x, &sortwrapper_type) ||
- !PyObject_TypeCheck(y, &sortwrapper_type)) {
- PyErr_SetString(PyExc_TypeError,
- "expected a sortwrapperobject");
- return NULL;
- }
- xx = ((sortwrapperobject *)x)->key;
- yy = ((sortwrapperobject *)y)->key;
- return PyObject_CallFunctionObjArgs(co->func, xx, yy, NULL);
-}
-
-PyDoc_STRVAR(cmpwrapper_doc, "cmp() wrapper for sort with custom keys.");
-
-static PyTypeObject cmpwrapper_type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "cmpwrapper", /* tp_name */
- sizeof(cmpwrapperobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)cmpwrapper_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- (ternaryfunc)cmpwrapper_call, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- cmpwrapper_doc, /* tp_doc */
-};
-
-static PyObject *
-build_cmpwrapper(PyObject *cmpfunc)
-{
- cmpwrapperobject *co;
-
- co = PyObject_New(cmpwrapperobject, &cmpwrapper_type);
- if (co == NULL)
- return NULL;
- Py_INCREF(cmpfunc);
- co->func = cmpfunc;
- return (PyObject *)co;
-}
-
-/* An adaptive, stable, natural mergesort. See listsort.txt.
- * Returns Py_None on success, NULL on error. Even in case of error, the
- * list will be some permutation of its input state (nothing is lost or
- * duplicated).
- */
-static PyObject *
-listsort(PyListObject *self, PyObject *args, PyObject *kwds)
-{
- MergeState ms;
- PyObject **lo, **hi;
- Py_ssize_t nremaining;
- Py_ssize_t minrun;
- Py_ssize_t saved_ob_size, saved_allocated;
- PyObject **saved_ob_item;
- PyObject **final_ob_item;
- PyObject *compare = NULL;
- PyObject *result = NULL; /* guilty until proved innocent */
- int reverse = 0;
- PyObject *keyfunc = NULL;
- Py_ssize_t i;
- PyObject *key, *value, *kvpair;
- static char *kwlist[] = {"cmp", "key", "reverse", 0};
-
- assert(self != NULL);
- assert (PyList_Check(self));
- if (args != NULL) {
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOi:sort",
- kwlist, &compare, &keyfunc, &reverse))
- return NULL;
- }
- if (compare == Py_None)
- compare = NULL;
- if (keyfunc == Py_None)
- keyfunc = NULL;
- if (compare != NULL && keyfunc != NULL) {
- compare = build_cmpwrapper(compare);
- if (compare == NULL)
- return NULL;
- } else
- Py_XINCREF(compare);
-
- /* The list is temporarily made empty, so that mutations performed
- * by comparison functions can't affect the slice of memory we're
- * sorting (allowing mutations during sorting is a core-dump
- * factory, since ob_item may change).
- */
- saved_ob_size = self->ob_size;
- saved_ob_item = self->ob_item;
- saved_allocated = self->allocated;
- self->ob_size = 0;
- self->ob_item = NULL;
- self->allocated = -1; /* any operation will reset it to >= 0 */
-
- if (keyfunc != NULL) {
- for (i=0 ; i < saved_ob_size ; i++) {
- value = saved_ob_item[i];
- key = PyObject_CallFunctionObjArgs(keyfunc, value,
- NULL);
- if (key == NULL) {
- for (i=i-1 ; i>=0 ; i--) {
- kvpair = saved_ob_item[i];
- value = sortwrapper_getvalue(kvpair);
- saved_ob_item[i] = value;
- Py_DECREF(kvpair);
- }
- goto dsu_fail;
- }
- kvpair = build_sortwrapper(key, value);
- if (kvpair == NULL)
- goto dsu_fail;
- saved_ob_item[i] = kvpair;
- }
- }
-
- /* Reverse sort stability achieved by initially reversing the list,
- applying a stable forward sort, then reversing the final result. */
- if (reverse && saved_ob_size > 1)
- reverse_slice(saved_ob_item, saved_ob_item + saved_ob_size);
-
- merge_init(&ms, compare);
-
- nremaining = saved_ob_size;
- if (nremaining < 2)
- goto succeed;
-
- /* March over the array once, left to right, finding natural runs,
- * and extending short natural runs to minrun elements.
- */
- lo = saved_ob_item;
- hi = lo + nremaining;
- minrun = merge_compute_minrun(nremaining);
- do {
- int descending;
- Py_ssize_t n;
-
- /* Identify next run. */
- n = count_run(lo, hi, compare, &descending);
- if (n < 0)
- goto fail;
- if (descending)
- reverse_slice(lo, lo + n);
- /* If short, extend to min(minrun, nremaining). */
- if (n < minrun) {
- const Py_ssize_t force = nremaining <= minrun ?
- nremaining : minrun;
- if (binarysort(lo, lo + force, lo + n, compare) < 0)
- goto fail;
- n = force;
- }
- /* Push run onto pending-runs stack, and maybe merge. */
- assert(ms.n < MAX_MERGE_PENDING);
- ms.pending[ms.n].base = lo;
- ms.pending[ms.n].len = n;
- ++ms.n;
- if (merge_collapse(&ms) < 0)
- goto fail;
- /* Advance to find next run. */
- lo += n;
- nremaining -= n;
- } while (nremaining);
- assert(lo == hi);
-
- if (merge_force_collapse(&ms) < 0)
- goto fail;
- assert(ms.n == 1);
- assert(ms.pending[0].base == saved_ob_item);
- assert(ms.pending[0].len == saved_ob_size);
-
-succeed:
- result = Py_None;
-fail:
- if (keyfunc != NULL) {
- for (i=0 ; i < saved_ob_size ; i++) {
- kvpair = saved_ob_item[i];
- value = sortwrapper_getvalue(kvpair);
- saved_ob_item[i] = value;
- Py_DECREF(kvpair);
- }
- }
-
- if (self->allocated != -1 && result != NULL) {
- /* The user mucked with the list during the sort,
- * and we don't already have another error to report.
- */
- PyErr_SetString(PyExc_ValueError, "list modified during sort");
- result = NULL;
- }
-
- if (reverse && saved_ob_size > 1)
- reverse_slice(saved_ob_item, saved_ob_item + saved_ob_size);
-
- merge_freemem(&ms);
-
-dsu_fail:
- final_ob_item = self->ob_item;
- i = self->ob_size;
- self->ob_size = saved_ob_size;
- self->ob_item = saved_ob_item;
- self->allocated = saved_allocated;
- if (final_ob_item != NULL) {
- /* we cannot use list_clear() for this because it does not
- guarantee that the list is really empty when it returns */
- while (--i >= 0) {
- Py_XDECREF(final_ob_item[i]);
- }
- PyMem_FREE(final_ob_item);
- }
- Py_XDECREF(compare);
- Py_XINCREF(result);
- return result;
-}
-#undef IFLT
-#undef ISLT
-
-int
-PyList_Sort(PyObject *v)
-{
- if (v == NULL || !PyList_Check(v)) {
- PyErr_BadInternalCall();
- return -1;
- }
- v = listsort((PyListObject *)v, (PyObject *)NULL, (PyObject *)NULL);
- if (v == NULL)
- return -1;
- Py_DECREF(v);
- return 0;
-}
-
-static PyObject *
-listreverse(PyListObject *self)
-{
- if (self->ob_size > 1)
- reverse_slice(self->ob_item, self->ob_item + self->ob_size);
- Py_RETURN_NONE;
-}
-
-int
-PyList_Reverse(PyObject *v)
-{
- PyListObject *self = (PyListObject *)v;
-
- if (v == NULL || !PyList_Check(v)) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (self->ob_size > 1)
- reverse_slice(self->ob_item, self->ob_item + self->ob_size);
- return 0;
-}
-
-PyObject *
-PyList_AsTuple(PyObject *v)
-{
- PyObject *w;
- PyObject **p;
- Py_ssize_t n;
- if (v == NULL || !PyList_Check(v)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- n = ((PyListObject *)v)->ob_size;
- w = PyTuple_New(n);
- if (w == NULL)
- return NULL;
- p = ((PyTupleObject *)w)->ob_item;
- memcpy((void *)p,
- (void *)((PyListObject *)v)->ob_item,
- n*sizeof(PyObject *));
- while (--n >= 0) {
- Py_INCREF(*p);
- p++;
- }
- return w;
-}
-
-static PyObject *
-listindex(PyListObject *self, PyObject *args)
-{
- Py_ssize_t i, start=0, stop=self->ob_size;
- PyObject *v;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,
- _PyEval_SliceIndex, &start,
- _PyEval_SliceIndex, &stop))
- return NULL;
- if (start < 0) {
- start += self->ob_size;
- if (start < 0)
- start = 0;
- }
- if (stop < 0) {
- stop += self->ob_size;
- if (stop < 0)
- stop = 0;
- }
- for (i = start; i < stop && i < self->ob_size; i++) {
- int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
- if (cmp > 0)
- return PyInt_FromSsize_t(i);
- else if (cmp < 0)
- return NULL;
- }
- PyErr_SetString(PyExc_ValueError, "list.index(x): x not in list");
- return NULL;
-}
-
-static PyObject *
-listcount(PyListObject *self, PyObject *v)
-{
- Py_ssize_t count = 0;
- Py_ssize_t i;
-
- for (i = 0; i < self->ob_size; i++) {
- int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
- if (cmp > 0)
- count++;
- else if (cmp < 0)
- return NULL;
- }
- return PyInt_FromSsize_t(count);
-}
-
-static PyObject *
-listremove(PyListObject *self, PyObject *v)
-{
- Py_ssize_t i;
-
- for (i = 0; i < self->ob_size; i++) {
- int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
- if (cmp > 0) {
- if (list_ass_slice(self, i, i+1,
- (PyObject *)NULL) == 0)
- Py_RETURN_NONE;
- return NULL;
- }
- else if (cmp < 0)
- return NULL;
- }
- PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");
- return NULL;
-}
-
-static int
-list_traverse(PyListObject *o, visitproc visit, void *arg)
-{
- Py_ssize_t i;
-
- for (i = o->ob_size; --i >= 0; )
- Py_VISIT(o->ob_item[i]);
- return 0;
-}
-
-static PyObject *
-list_richcompare(PyObject *v, PyObject *w, int op)
-{
- PyListObject *vl, *wl;
- Py_ssize_t i;
-
- if (!PyList_Check(v) || !PyList_Check(w)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- vl = (PyListObject *)v;
- wl = (PyListObject *)w;
-
- if (vl->ob_size != wl->ob_size && (op == Py_EQ || op == Py_NE)) {
- /* Shortcut: if the lengths differ, the lists differ */
- PyObject *res;
- if (op == Py_EQ)
- res = Py_False;
- else
- res = Py_True;
- Py_INCREF(res);
- return res;
- }
-
- /* Search for the first index where items are different */
- for (i = 0; i < vl->ob_size && i < wl->ob_size; i++) {
- int k = PyObject_RichCompareBool(vl->ob_item[i],
- wl->ob_item[i], Py_EQ);
- if (k < 0)
- return NULL;
- if (!k)
- break;
- }
-
- if (i >= vl->ob_size || i >= wl->ob_size) {
- /* No more items to compare -- compare sizes */
- Py_ssize_t vs = vl->ob_size;
- Py_ssize_t ws = wl->ob_size;
- int cmp;
- PyObject *res;
- switch (op) {
- case Py_LT: cmp = vs < ws; break;
- case Py_LE: cmp = vs <= ws; break;
- case Py_EQ: cmp = vs == ws; break;
- case Py_NE: cmp = vs != ws; break;
- case Py_GT: cmp = vs > ws; break;
- case Py_GE: cmp = vs >= ws; break;
- default: return NULL; /* cannot happen */
- }
- if (cmp)
- res = Py_True;
- else
- res = Py_False;
- Py_INCREF(res);
- return res;
- }
-
- /* We have an item that differs -- shortcuts for EQ/NE */
- if (op == Py_EQ) {
- Py_INCREF(Py_False);
- return Py_False;
- }
- if (op == Py_NE) {
- Py_INCREF(Py_True);
- return Py_True;
- }
-
- /* Compare the final item again using the proper operator */
- return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op);
-}
-
-static int
-list_init(PyListObject *self, PyObject *args, PyObject *kw)
-{
- PyObject *arg = NULL;
- static char *kwlist[] = {"sequence", 0};
-
- if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg))
- return -1;
-
- /* Verify list invariants established by PyType_GenericAlloc() */
- assert(0 <= self->ob_size);
- assert(self->ob_size <= self->allocated || self->allocated == -1);
- assert(self->ob_item != NULL ||
- self->allocated == 0 || self->allocated == -1);
-
- /* Empty previous contents */
- if (self->ob_item != NULL) {
- (void)list_clear(self);
- }
- if (arg != NULL) {
- PyObject *rv = listextend(self, arg);
- if (rv == NULL)
- return -1;
- Py_DECREF(rv);
- }
- return 0;
-}
-
-static long
-list_nohash(PyObject *self)
-{
- PyErr_SetString(PyExc_TypeError, "list objects are unhashable");
- return -1;
-}
-
-static PyObject *list_iter(PyObject *seq);
-static PyObject *list_reversed(PyListObject* seq, PyObject* unused);
-
-PyDoc_STRVAR(getitem_doc,
-"x.__getitem__(y) <==> x[y]");
-PyDoc_STRVAR(reversed_doc,
-"L.__reversed__() -- return a reverse iterator over the list");
-PyDoc_STRVAR(append_doc,
-"L.append(object) -- append object to end");
-PyDoc_STRVAR(extend_doc,
-"L.extend(iterable) -- extend list by appending elements from the iterable");
-PyDoc_STRVAR(insert_doc,
-"L.insert(index, object) -- insert object before index");
-PyDoc_STRVAR(pop_doc,
-"L.pop([index]) -> item -- remove and return item at index (default last)");
-PyDoc_STRVAR(remove_doc,
-"L.remove(value) -- remove first occurrence of value");
-PyDoc_STRVAR(index_doc,
-"L.index(value, [start, [stop]]) -> integer -- return first index of value");
-PyDoc_STRVAR(count_doc,
-"L.count(value) -> integer -- return number of occurrences of value");
-PyDoc_STRVAR(reverse_doc,
-"L.reverse() -- reverse *IN PLACE*");
-PyDoc_STRVAR(sort_doc,
-"L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;\n\
-cmp(x, y) -> -1, 0, 1");
-
-static PyObject *list_subscript(PyListObject*, PyObject*);
-
-static PyMethodDef list_methods[] = {
- {"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, getitem_doc},
- {"__reversed__",(PyCFunction)list_reversed, METH_NOARGS, reversed_doc},
- {"append", (PyCFunction)listappend, METH_O, append_doc},
- {"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc},
- {"extend", (PyCFunction)listextend, METH_O, extend_doc},
- {"pop", (PyCFunction)listpop, METH_VARARGS, pop_doc},
- {"remove", (PyCFunction)listremove, METH_O, remove_doc},
- {"index", (PyCFunction)listindex, METH_VARARGS, index_doc},
- {"count", (PyCFunction)listcount, METH_O, count_doc},
- {"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc},
- {"sort", (PyCFunction)listsort, METH_VARARGS | METH_KEYWORDS, sort_doc},
- {NULL, NULL} /* sentinel */
-};
-
-static PySequenceMethods list_as_sequence = {
- (lenfunc)list_length, /* sq_length */
- (binaryfunc)list_concat, /* sq_concat */
- (ssizeargfunc)list_repeat, /* sq_repeat */
- (ssizeargfunc)list_item, /* sq_item */
- (ssizessizeargfunc)list_slice, /* sq_slice */
- (ssizeobjargproc)list_ass_item, /* sq_ass_item */
- (ssizessizeobjargproc)list_ass_slice, /* sq_ass_slice */
- (objobjproc)list_contains, /* sq_contains */
- (binaryfunc)list_inplace_concat, /* sq_inplace_concat */
- (ssizeargfunc)list_inplace_repeat, /* sq_inplace_repeat */
-};
-
-PyDoc_STRVAR(list_doc,
-"list() -> new list\n"
-"list(sequence) -> new list initialized from sequence's items");
-
-
-static PyObject *
-list_subscript(PyListObject* self, PyObject* item)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i;
- i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += PyList_GET_SIZE(self);
- return list_item(self, i);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength, cur, i;
- PyObject* result;
- PyObject* it;
- PyObject **src, **dest;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, self->ob_size,
- &start, &stop, &step, &slicelength) < 0) {
- return NULL;
- }
-
- if (slicelength <= 0) {
- return PyList_New(0);
- }
- else {
- result = PyList_New(slicelength);
- if (!result) return NULL;
-
- src = self->ob_item;
- dest = ((PyListObject *)result)->ob_item;
- for (cur = start, i = 0; i < slicelength;
- cur += step, i++) {
- it = src[cur];
- Py_INCREF(it);
- dest[i] = it;
- }
-
- return result;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "list indices must be integers");
- return NULL;
- }
-}
-
-static int
-list_ass_subscript(PyListObject* self, PyObject* item, PyObject* value)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return -1;
- if (i < 0)
- i += PyList_GET_SIZE(self);
- return list_ass_item(self, i, value);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, self->ob_size,
- &start, &stop, &step, &slicelength) < 0) {
- return -1;
- }
-
- /* treat L[slice(a,b)] = v _exactly_ like L[a:b] = v */
- if (step == 1 && ((PySliceObject*)item)->step == Py_None)
- return list_ass_slice(self, start, stop, value);
-
- if (value == NULL) {
- /* delete slice */
- PyObject **garbage;
- Py_ssize_t cur, i;
-
- if (slicelength <= 0)
- return 0;
-
- if (step < 0) {
- stop = start + 1;
- start = stop + step*(slicelength - 1) - 1;
- step = -step;
- }
-
- garbage = (PyObject**)
- PyMem_MALLOC(slicelength*sizeof(PyObject*));
- if (!garbage) {
- PyErr_NoMemory();
- return -1;
- }
-
- /* drawing pictures might help
- understand these for loops */
- for (cur = start, i = 0;
- cur < stop;
- cur += step, i++) {
- Py_ssize_t lim = step;
-
- garbage[i] = PyList_GET_ITEM(self, cur);
-
- if (cur + step >= self->ob_size) {
- lim = self->ob_size - cur - 1;
- }
-
- memmove(self->ob_item + cur - i,
- self->ob_item + cur + 1,
- lim * sizeof(PyObject *));
- }
-
- for (cur = start + slicelength*step + 1;
- cur < self->ob_size; cur++) {
- PyList_SET_ITEM(self, cur - slicelength,
- PyList_GET_ITEM(self, cur));
- }
-
- self->ob_size -= slicelength;
- list_resize(self, self->ob_size);
-
- for (i = 0; i < slicelength; i++) {
- Py_DECREF(garbage[i]);
- }
- PyMem_FREE(garbage);
-
- return 0;
- }
- else {
- /* assign slice */
- PyObject **garbage, *ins, *seq, **seqitems, **selfitems;
- Py_ssize_t cur, i;
-
- /* protect against a[::-1] = a */
- if (self == (PyListObject*)value) {
- seq = list_slice((PyListObject*)value, 0,
- PyList_GET_SIZE(value));
- }
- else {
- seq = PySequence_Fast(value,
- "must assign iterable to extended slice");
- }
- if (!seq)
- return -1;
-
- if (PySequence_Fast_GET_SIZE(seq) != slicelength) {
- PyErr_Format(PyExc_ValueError,
- "attempt to assign sequence of size %zd to extended slice of size %zd",
- PySequence_Fast_GET_SIZE(seq),
- slicelength);
- Py_DECREF(seq);
- return -1;
- }
-
- if (!slicelength) {
- Py_DECREF(seq);
- return 0;
- }
-
- garbage = (PyObject**)
- PyMem_MALLOC(slicelength*sizeof(PyObject*));
- if (!garbage) {
- Py_DECREF(seq);
- PyErr_NoMemory();
- return -1;
- }
-
- selfitems = self->ob_item;
- seqitems = PySequence_Fast_ITEMS(seq);
- for (cur = start, i = 0; i < slicelength;
- cur += step, i++) {
- garbage[i] = selfitems[cur];
- ins = seqitems[i];
- Py_INCREF(ins);
- selfitems[cur] = ins;
- }
-
- for (i = 0; i < slicelength; i++) {
- Py_DECREF(garbage[i]);
- }
-
- PyMem_FREE(garbage);
- Py_DECREF(seq);
-
- return 0;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "list indices must be integers");
- return -1;
- }
-}
-
-static PyMappingMethods list_as_mapping = {
- (lenfunc)list_length,
- (binaryfunc)list_subscript,
- (objobjargproc)list_ass_subscript
-};
-
-PyTypeObject PyList_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "list",
- sizeof(PyListObject),
- 0,
- (destructor)list_dealloc, /* tp_dealloc */
- (printfunc)list_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)list_repr, /* tp_repr */
- 0, /* tp_as_number */
- &list_as_sequence, /* tp_as_sequence */
- &list_as_mapping, /* tp_as_mapping */
- list_nohash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- list_doc, /* tp_doc */
- (traverseproc)list_traverse, /* tp_traverse */
- (inquiry)list_clear, /* tp_clear */
- list_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- list_iter, /* tp_iter */
- 0, /* tp_iternext */
- list_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)list_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-
-/*********************** List Iterator **************************/
-
-typedef struct {
- PyObject_HEAD
- long it_index;
- PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
-} listiterobject;
-
-static PyObject *list_iter(PyObject *);
-static void listiter_dealloc(listiterobject *);
-static int listiter_traverse(listiterobject *, visitproc, void *);
-static PyObject *listiter_next(listiterobject *);
-static PyObject *listiter_len(listiterobject *);
-
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
-
-static PyMethodDef listiter_methods[] = {
- {"__length_hint__", (PyCFunction)listiter_len, METH_NOARGS, length_hint_doc},
- {NULL, NULL} /* sentinel */
-};
-
-PyTypeObject PyListIter_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "listiterator", /* tp_name */
- sizeof(listiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)listiter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)listiter_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)listiter_next, /* tp_iternext */
- listiter_methods, /* tp_methods */
- 0, /* tp_members */
-};
-
-
-static PyObject *
-list_iter(PyObject *seq)
-{
- listiterobject *it;
-
- if (!PyList_Check(seq)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- it = PyObject_GC_New(listiterobject, &PyListIter_Type);
- if (it == NULL)
- return NULL;
- it->it_index = 0;
- Py_INCREF(seq);
- it->it_seq = (PyListObject *)seq;
- _PyObject_GC_TRACK(it);
- return (PyObject *)it;
-}
-
-static void
-listiter_dealloc(listiterobject *it)
-{
- _PyObject_GC_UNTRACK(it);
- Py_XDECREF(it->it_seq);
- PyObject_GC_Del(it);
-}
-
-static int
-listiter_traverse(listiterobject *it, visitproc visit, void *arg)
-{
- Py_VISIT(it->it_seq);
- return 0;
-}
-
-static PyObject *
-listiter_next(listiterobject *it)
-{
- PyListObject *seq;
- PyObject *item;
-
- assert(it != NULL);
- seq = it->it_seq;
- if (seq == NULL)
- return NULL;
- assert(PyList_Check(seq));
-
- if (it->it_index < PyList_GET_SIZE(seq)) {
- item = PyList_GET_ITEM(seq, it->it_index);
- ++it->it_index;
- Py_INCREF(item);
- return item;
- }
-
- Py_DECREF(seq);
- it->it_seq = NULL;
- return NULL;
-}
-
-static PyObject *
-listiter_len(listiterobject *it)
-{
- Py_ssize_t len;
- if (it->it_seq) {
- len = PyList_GET_SIZE(it->it_seq) - it->it_index;
- if (len >= 0)
- return PyInt_FromSsize_t(len);
- }
- return PyInt_FromLong(0);
-}
-/*********************** List Reverse Iterator **************************/
-
-typedef struct {
- PyObject_HEAD
- Py_ssize_t it_index;
- PyListObject *it_seq; /* Set to NULL when iterator is exhausted */
-} listreviterobject;
-
-static PyObject *list_reversed(PyListObject *, PyObject *);
-static void listreviter_dealloc(listreviterobject *);
-static int listreviter_traverse(listreviterobject *, visitproc, void *);
-static PyObject *listreviter_next(listreviterobject *);
-static Py_ssize_t listreviter_len(listreviterobject *);
-
-static PySequenceMethods listreviter_as_sequence = {
- (lenfunc)listreviter_len, /* sq_length */
- 0, /* sq_concat */
-};
-
-PyTypeObject PyListRevIter_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "listreverseiterator", /* tp_name */
- sizeof(listreviterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)listreviter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- &listreviter_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)listreviter_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)listreviter_next, /* tp_iternext */
- 0,
-};
-
-static PyObject *
-list_reversed(PyListObject *seq, PyObject *unused)
-{
- listreviterobject *it;
-
- it = PyObject_GC_New(listreviterobject, &PyListRevIter_Type);
- if (it == NULL)
- return NULL;
- assert(PyList_Check(seq));
- it->it_index = PyList_GET_SIZE(seq) - 1;
- Py_INCREF(seq);
- it->it_seq = seq;
- PyObject_GC_Track(it);
- return (PyObject *)it;
-}
-
-static void
-listreviter_dealloc(listreviterobject *it)
-{
- PyObject_GC_UnTrack(it);
- Py_XDECREF(it->it_seq);
- PyObject_GC_Del(it);
-}
-
-static int
-listreviter_traverse(listreviterobject *it, visitproc visit, void *arg)
-{
- Py_VISIT(it->it_seq);
- return 0;
-}
-
-static PyObject *
-listreviter_next(listreviterobject *it)
-{
- PyObject *item;
- Py_ssize_t index = it->it_index;
- PyListObject *seq = it->it_seq;
-
- if (index>=0 && index < PyList_GET_SIZE(seq)) {
- item = PyList_GET_ITEM(seq, index);
- it->it_index--;
- Py_INCREF(item);
- return item;
- }
- it->it_index = -1;
- if (seq != NULL) {
- it->it_seq = NULL;
- Py_DECREF(seq);
- }
- return NULL;
-}
-
-static Py_ssize_t
-listreviter_len(listreviterobject *it)
-{
- Py_ssize_t len = it->it_index + 1;
- if (it->it_seq == NULL || PyList_GET_SIZE(it->it_seq) < len)
- return 0;
- return len;
-}
-
diff --git a/sys/src/cmd/python/Objects/listsort.txt b/sys/src/cmd/python/Objects/listsort.txt
deleted file mode 100644
index 92269840e..000000000
--- a/sys/src/cmd/python/Objects/listsort.txt
+++ /dev/null
@@ -1,677 +0,0 @@
-Intro
------
-This describes an adaptive, stable, natural mergesort, modestly called
-timsort (hey, I earned it <wink>). It has supernatural performance on many
-kinds of partially ordered arrays (less than lg(N!) comparisons needed, and
-as few as N-1), yet as fast as Python's previous highly tuned samplesort
-hybrid on random arrays.
-
-In a nutshell, the main routine marches over the array once, left to right,
-alternately identifying the next run, then merging it into the previous
-runs "intelligently". Everything else is complication for speed, and some
-hard-won measure of memory efficiency.
-
-
-Comparison with Python's Samplesort Hybrid
-------------------------------------------
-+ timsort can require a temp array containing as many as N//2 pointers,
- which means as many as 2*N extra bytes on 32-bit boxes. It can be
- expected to require a temp array this large when sorting random data; on
- data with significant structure, it may get away without using any extra
- heap memory. This appears to be the strongest argument against it, but
- compared to the size of an object, 2 temp bytes worst-case (also expected-
- case for random data) doesn't scare me much.
-
- It turns out that Perl is moving to a stable mergesort, and the code for
- that appears always to require a temp array with room for at least N
- pointers. (Note that I wouldn't want to do that even if space weren't an
- issue; I believe its efforts at memory frugality also save timsort
- significant pointer-copying costs, and allow it to have a smaller working
- set.)
-
-+ Across about four hours of generating random arrays, and sorting them
- under both methods, samplesort required about 1.5% more comparisons
- (the program is at the end of this file).
-
-+ In real life, this may be faster or slower on random arrays than
- samplesort was, depending on platform quirks. Since it does fewer
- comparisons on average, it can be expected to do better the more
- expensive a comparison function is. OTOH, it does more data movement
- (pointer copying) than samplesort, and that may negate its small
- comparison advantage (depending on platform quirks) unless comparison
- is very expensive.
-
-+ On arrays with many kinds of pre-existing order, this blows samplesort out
- of the water. It's significantly faster than samplesort even on some
- cases samplesort was special-casing the snot out of. I believe that lists
- very often do have exploitable partial order in real life, and this is the
- strongest argument in favor of timsort (indeed, samplesort's special cases
- for extreme partial order are appreciated by real users, and timsort goes
- much deeper than those, in particular naturally covering every case where
- someone has suggested "and it would be cool if list.sort() had a special
- case for this too ... and for that ...").
-
-+ Here are exact comparison counts across all the tests in sortperf.py,
- when run with arguments "15 20 1".
-
- Column Key:
- *sort: random data
- \sort: descending data
- /sort: ascending data
- 3sort: ascending, then 3 random exchanges
- +sort: ascending, then 10 random at the end
- ~sort: many duplicates
- =sort: all equal
- !sort: worst case scenario
-
- First the trivial cases, trivial for samplesort because it special-cased
- them, and trivial for timsort because it naturally works on runs. Within
- an "n" block, the first line gives the # of compares done by samplesort,
- the second line by timsort, and the third line is the percentage by
- which the samplesort count exceeds the timsort count:
-
- n \sort /sort =sort
-------- ------ ------ ------
- 32768 32768 32767 32767 samplesort
- 32767 32767 32767 timsort
- 0.00% 0.00% 0.00% (samplesort - timsort) / timsort
-
- 65536 65536 65535 65535
- 65535 65535 65535
- 0.00% 0.00% 0.00%
-
- 131072 131072 131071 131071
- 131071 131071 131071
- 0.00% 0.00% 0.00%
-
- 262144 262144 262143 262143
- 262143 262143 262143
- 0.00% 0.00% 0.00%
-
- 524288 524288 524287 524287
- 524287 524287 524287
- 0.00% 0.00% 0.00%
-
-1048576 1048576 1048575 1048575
- 1048575 1048575 1048575
- 0.00% 0.00% 0.00%
-
- The algorithms are effectively identical in these cases, except that
- timsort does one less compare in \sort.
-
- Now for the more interesting cases. lg(n!) is the information-theoretic
- limit for the best any comparison-based sorting algorithm can do on
- average (across all permutations). When a method gets significantly
- below that, it's either astronomically lucky, or is finding exploitable
- structure in the data.
-
- n lg(n!) *sort 3sort +sort %sort ~sort !sort
-------- ------- ------ ------- ------- ------ ------- --------
- 32768 444255 453096 453614 32908 452871 130491 469141 old
- 448885 33016 33007 50426 182083 65534 new
- 0.94% 1273.92% -0.30% 798.09% -28.33% 615.87% %ch from new
-
- 65536 954037 972699 981940 65686 973104 260029 1004607
- 962991 65821 65808 101667 364341 131070
- 1.01% 1391.83% -0.19% 857.15% -28.63% 666.47%
-
- 131072 2039137 2101881 2091491 131232 2092894 554790 2161379
- 2057533 131410 131361 206193 728871 262142
- 2.16% 1491.58% -0.10% 915.02% -23.88% 724.51%
-
- 262144 4340409 4464460 4403233 262314 4445884 1107842 4584560
- 4377402 262437 262459 416347 1457945 524286
- 1.99% 1577.82% -0.06% 967.83% -24.01% 774.44%
-
- 524288 9205096 9453356 9408463 524468 9441930 2218577 9692015
- 9278734 524580 524633 837947 2916107 1048574
- 1.88% 1693.52% -0.03% 1026.79% -23.92% 824.30%
-
-1048576 19458756 19950272 19838588 1048766 19912134 4430649 20434212
- 19606028 1048958 1048941 1694896 5832445 2097150
- 1.76% 1791.27% -0.02% 1074.83% -24.03% 874.38%
-
- Discussion of cases:
-
- *sort: There's no structure in random data to exploit, so the theoretical
- limit is lg(n!). Both methods get close to that, and timsort is hugging
- it (indeed, in a *marginal* sense, it's a spectacular improvement --
- there's only about 1% left before hitting the wall, and timsort knows
- darned well it's doing compares that won't pay on random data -- but so
- does the samplesort hybrid). For contrast, Hoare's original random-pivot
- quicksort does about 39% more compares than the limit, and the median-of-3
- variant about 19% more.
-
- 3sort, %sort, and !sort: No contest; there's structure in this data, but
- not of the specific kinds samplesort special-cases. Note that structure
- in !sort wasn't put there on purpose -- it was crafted as a worst case for
- a previous quicksort implementation. That timsort nails it came as a
- surprise to me (although it's obvious in retrospect).
-
- +sort: samplesort special-cases this data, and does a few less compares
- than timsort. However, timsort runs this case significantly faster on all
- boxes we have timings for, because timsort is in the business of merging
- runs efficiently, while samplesort does much more data movement in this
- (for it) special case.
-
- ~sort: samplesort's special cases for large masses of equal elements are
- extremely effective on ~sort's specific data pattern, and timsort just
- isn't going to get close to that, despite that it's clearly getting a
- great deal of benefit out of the duplicates (the # of compares is much less
- than lg(n!)). ~sort has a perfectly uniform distribution of just 4
- distinct values, and as the distribution gets more skewed, samplesort's
- equal-element gimmicks become less effective, while timsort's adaptive
- strategies find more to exploit; in a database supplied by Kevin Altis, a
- sort on its highly skewed "on which stock exchange does this company's
- stock trade?" field ran over twice as fast under timsort.
-
- However, despite that timsort does many more comparisons on ~sort, and
- that on several platforms ~sort runs highly significantly slower under
- timsort, on other platforms ~sort runs highly significantly faster under
- timsort. No other kind of data has shown this wild x-platform behavior,
- and we don't have an explanation for it. The only thing I can think of
- that could transform what "should be" highly significant slowdowns into
- highly significant speedups on some boxes are catastrophic cache effects
- in samplesort.
-
- But timsort "should be" slower than samplesort on ~sort, so it's hard
- to count that it isn't on some boxes as a strike against it <wink>.
-
-+ Here's the highwater mark for the number of heap-based temp slots (4
- bytes each on this box) needed by each test, again with arguments
- "15 20 1":
-
- 2**i *sort \sort /sort 3sort +sort %sort ~sort =sort !sort
- 32768 16384 0 0 6256 0 10821 12288 0 16383
- 65536 32766 0 0 21652 0 31276 24576 0 32767
- 131072 65534 0 0 17258 0 58112 49152 0 65535
- 262144 131072 0 0 35660 0 123561 98304 0 131071
- 524288 262142 0 0 31302 0 212057 196608 0 262143
-1048576 524286 0 0 312438 0 484942 393216 0 524287
-
- Discussion: The tests that end up doing (close to) perfectly balanced
- merges (*sort, !sort) need all N//2 temp slots (or almost all). ~sort
- also ends up doing balanced merges, but systematically benefits a lot from
- the preliminary pre-merge searches described under "Merge Memory" later.
- %sort approaches having a balanced merge at the end because the random
- selection of elements to replace is expected to produce an out-of-order
- element near the midpoint. \sort, /sort, =sort are the trivial one-run
- cases, needing no merging at all. +sort ends up having one very long run
- and one very short, and so gets all the temp space it needs from the small
- temparray member of the MergeState struct (note that the same would be
- true if the new random elements were prefixed to the sorted list instead,
- but not if they appeared "in the middle"). 3sort approaches N//3 temp
- slots twice, but the run lengths that remain after 3 random exchanges
- clearly has very high variance.
-
-
-A detailed description of timsort follows.
-
-Runs
-----
-count_run() returns the # of elements in the next run. A run is either
-"ascending", which means non-decreasing:
-
- a0 <= a1 <= a2 <= ...
-
-or "descending", which means strictly decreasing:
-
- a0 > a1 > a2 > ...
-
-Note that a run is always at least 2 long, unless we start at the array's
-last element.
-
-The definition of descending is strict, because the main routine reverses
-a descending run in-place, transforming a descending run into an ascending
-run. Reversal is done via the obvious fast "swap elements starting at each
-end, and converge at the middle" method, and that can violate stability if
-the slice contains any equal elements. Using a strict definition of
-descending ensures that a descending run contains distinct elements.
-
-If an array is random, it's very unlikely we'll see long runs. If a natural
-run contains less than minrun elements (see next section), the main loop
-artificially boosts it to minrun elements, via a stable binary insertion sort
-applied to the right number of array elements following the short natural
-run. In a random array, *all* runs are likely to be minrun long as a
-result. This has two primary good effects:
-
-1. Random data strongly tends then toward perfectly balanced (both runs have
- the same length) merges, which is the most efficient way to proceed when
- data is random.
-
-2. Because runs are never very short, the rest of the code doesn't make
- heroic efforts to shave a few cycles off per-merge overheads. For
- example, reasonable use of function calls is made, rather than trying to
- inline everything. Since there are no more than N/minrun runs to begin
- with, a few "extra" function calls per merge is barely measurable.
-
-
-Computing minrun
-----------------
-If N < 64, minrun is N. IOW, binary insertion sort is used for the whole
-array then; it's hard to beat that given the overheads of trying something
-fancier.
-
-When N is a power of 2, testing on random data showed that minrun values of
-16, 32, 64 and 128 worked about equally well. At 256 the data-movement cost
-in binary insertion sort clearly hurt, and at 8 the increase in the number
-of function calls clearly hurt. Picking *some* power of 2 is important
-here, so that the merges end up perfectly balanced (see next section). We
-pick 32 as a good value in the sweet range; picking a value at the low end
-allows the adaptive gimmicks more opportunity to exploit shorter natural
-runs.
-
-Because sortperf.py only tries powers of 2, it took a long time to notice
-that 32 isn't a good choice for the general case! Consider N=2112:
-
->>> divmod(2112, 32)
-(66, 0)
->>>
-
-If the data is randomly ordered, we're very likely to end up with 66 runs
-each of length 32. The first 64 of these trigger a sequence of perfectly
-balanced merges (see next section), leaving runs of lengths 2048 and 64 to
-merge at the end. The adaptive gimmicks can do that with fewer than 2048+64
-compares, but it's still more compares than necessary, and-- mergesort's
-bugaboo relative to samplesort --a lot more data movement (O(N) copies just
-to get 64 elements into place).
-
-If we take minrun=33 in this case, then we're very likely to end up with 64
-runs each of length 33, and then all merges are perfectly balanced. Better!
-
-What we want to avoid is picking minrun such that in
-
- q, r = divmod(N, minrun)
-
-q is a power of 2 and r>0 (then the last merge only gets r elements into
-place, and r < minrun is small compared to N), or q a little larger than a
-power of 2 regardless of r (then we've got a case similar to "2112", again
-leaving too little work for the last merge to do).
-
-Instead we pick a minrun in range(32, 65) such that N/minrun is exactly a
-power of 2, or if that isn't possible, is close to, but strictly less than,
-a power of 2. This is easier to do than it may sound: take the first 6
-bits of N, and add 1 if any of the remaining bits are set. In fact, that
-rule covers every case in this section, including small N and exact powers
-of 2; merge_compute_minrun() is a deceptively simple function.
-
-
-The Merge Pattern
------------------
-In order to exploit regularities in the data, we're merging on natural
-run lengths, and they can become wildly unbalanced. That's a Good Thing
-for this sort! It means we have to find a way to manage an assortment of
-potentially very different run lengths, though.
-
-Stability constrains permissible merging patterns. For example, if we have
-3 consecutive runs of lengths
-
- A:10000 B:20000 C:10000
-
-we dare not merge A with C first, because if A, B and C happen to contain
-a common element, it would get out of order wrt its occurence(s) in B. The
-merging must be done as (A+B)+C or A+(B+C) instead.
-
-So merging is always done on two consecutive runs at a time, and in-place,
-although this may require some temp memory (more on that later).
-
-When a run is identified, its base address and length are pushed on a stack
-in the MergeState struct. merge_collapse() is then called to see whether it
-should merge it with preceding run(s). We would like to delay merging as
-long as possible in order to exploit patterns that may come up later, but we
-like even more to do merging as soon as possible to exploit that the run just
-found is still high in the memory hierarchy. We also can't delay merging
-"too long" because it consumes memory to remember the runs that are still
-unmerged, and the stack has a fixed size.
-
-What turned out to be a good compromise maintains two invariants on the
-stack entries, where A, B and C are the lengths of the three righmost not-yet
-merged slices:
-
-1. A > B+C
-2. B > C
-
-Note that, by induction, #2 implies the lengths of pending runs form a
-decreasing sequence. #1 implies that, reading the lengths right to left,
-the pending-run lengths grow at least as fast as the Fibonacci numbers.
-Therefore the stack can never grow larger than about log_base_phi(N) entries,
-where phi = (1+sqrt(5))/2 ~= 1.618. Thus a small # of stack slots suffice
-for very large arrays.
-
-If A <= B+C, the smaller of A and C is merged with B (ties favor C, for the
-freshness-in-cache reason), and the new run replaces the A,B or B,C entries;
-e.g., if the last 3 entries are
-
- A:30 B:20 C:10
-
-then B is merged with C, leaving
-
- A:30 BC:30
-
-on the stack. Or if they were
-
- A:500 B:400: C:1000
-
-then A is merged with B, leaving
-
- AB:900 C:1000
-
-on the stack.
-
-In both examples, the stack configuration after the merge still violates
-invariant #2, and merge_collapse() goes on to continue merging runs until
-both invariants are satisfied. As an extreme case, suppose we didn't do the
-minrun gimmick, and natural runs were of lengths 128, 64, 32, 16, 8, 4, 2,
-and 2. Nothing would get merged until the final 2 was seen, and that would
-trigger 7 perfectly balanced merges.
-
-The thrust of these rules when they trigger merging is to balance the run
-lengths as closely as possible, while keeping a low bound on the number of
-runs we have to remember. This is maximally effective for random data,
-where all runs are likely to be of (artificially forced) length minrun, and
-then we get a sequence of perfectly balanced merges (with, perhaps, some
-oddballs at the end).
-
-OTOH, one reason this sort is so good for partly ordered data has to do
-with wildly unbalanced run lengths.
-
-
-Merge Memory
-------------
-Merging adjacent runs of lengths A and B in-place is very difficult.
-Theoretical constructions are known that can do it, but they're too difficult
-and slow for practical use. But if we have temp memory equal to min(A, B),
-it's easy.
-
-If A is smaller (function merge_lo), copy A to a temp array, leave B alone,
-and then we can do the obvious merge algorithm left to right, from the temp
-area and B, starting the stores into where A used to live. There's always a
-free area in the original area comprising a number of elements equal to the
-number not yet merged from the temp array (trivially true at the start;
-proceed by induction). The only tricky bit is that if a comparison raises an
-exception, we have to remember to copy the remaining elements back in from
-the temp area, lest the array end up with duplicate entries from B. But
-that's exactly the same thing we need to do if we reach the end of B first,
-so the exit code is pleasantly common to both the normal and error cases.
-
-If B is smaller (function merge_hi, which is merge_lo's "mirror image"),
-much the same, except that we need to merge right to left, copying B into a
-temp array and starting the stores at the right end of where B used to live.
-
-A refinement: When we're about to merge adjacent runs A and B, we first do
-a form of binary search (more on that later) to see where B[0] should end up
-in A. Elements in A preceding that point are already in their final
-positions, effectively shrinking the size of A. Likewise we also search to
-see where A[-1] should end up in B, and elements of B after that point can
-also be ignored. This cuts the amount of temp memory needed by the same
-amount.
-
-These preliminary searches may not pay off, and can be expected *not* to
-repay their cost if the data is random. But they can win huge in all of
-time, copying, and memory savings when they do pay, so this is one of the
-"per-merge overheads" mentioned above that we're happy to endure because
-there is at most one very short run. It's generally true in this algorithm
-that we're willing to gamble a little to win a lot, even though the net
-expectation is negative for random data.
-
-
-Merge Algorithms
-----------------
-merge_lo() and merge_hi() are where the bulk of the time is spent. merge_lo
-deals with runs where A <= B, and merge_hi where A > B. They don't know
-whether the data is clustered or uniform, but a lovely thing about merging
-is that many kinds of clustering "reveal themselves" by how many times in a
-row the winning merge element comes from the same run. We'll only discuss
-merge_lo here; merge_hi is exactly analogous.
-
-Merging begins in the usual, obvious way, comparing the first element of A
-to the first of B, and moving B[0] to the merge area if it's less than A[0],
-else moving A[0] to the merge area. Call that the "one pair at a time"
-mode. The only twist here is keeping track of how many times in a row "the
-winner" comes from the same run.
-
-If that count reaches MIN_GALLOP, we switch to "galloping mode". Here
-we *search* B for where A[0] belongs, and move over all the B's before
-that point in one chunk to the merge area, then move A[0] to the merge
-area. Then we search A for where B[0] belongs, and similarly move a
-slice of A in one chunk. Then back to searching B for where A[0] belongs,
-etc. We stay in galloping mode until both searches find slices to copy
-less than MIN_GALLOP elements long, at which point we go back to one-pair-
-at-a-time mode.
-
-A refinement: The MergeState struct contains the value of min_gallop that
-controls when we enter galloping mode, initialized to MIN_GALLOP.
-merge_lo() and merge_hi() adjust this higher when galloping isn't paying
-off, and lower when it is.
-
-
-Galloping
----------
-Still without loss of generality, assume A is the shorter run. In galloping
-mode, we first look for A[0] in B. We do this via "galloping", comparing
-A[0] in turn to B[0], B[1], B[3], B[7], ..., B[2**j - 1], ..., until finding
-the k such that B[2**(k-1) - 1] < A[0] <= B[2**k - 1]. This takes at most
-roughly lg(B) comparisons, and, unlike a straight binary search, favors
-finding the right spot early in B (more on that later).
-
-After finding such a k, the region of uncertainty is reduced to 2**(k-1) - 1
-consecutive elements, and a straight binary search requires exactly k-1
-additional comparisons to nail it. Then we copy all the B's up to that
-point in one chunk, and then copy A[0]. Note that no matter where A[0]
-belongs in B, the combination of galloping + binary search finds it in no
-more than about 2*lg(B) comparisons.
-
-If we did a straight binary search, we could find it in no more than
-ceiling(lg(B+1)) comparisons -- but straight binary search takes that many
-comparisons no matter where A[0] belongs. Straight binary search thus loses
-to galloping unless the run is quite long, and we simply can't guess
-whether it is in advance.
-
-If data is random and runs have the same length, A[0] belongs at B[0] half
-the time, at B[1] a quarter of the time, and so on: a consecutive winning
-sub-run in B of length k occurs with probability 1/2**(k+1). So long
-winning sub-runs are extremely unlikely in random data, and guessing that a
-winning sub-run is going to be long is a dangerous game.
-
-OTOH, if data is lopsided or lumpy or contains many duplicates, long
-stretches of winning sub-runs are very likely, and cutting the number of
-comparisons needed to find one from O(B) to O(log B) is a huge win.
-
-Galloping compromises by getting out fast if there isn't a long winning
-sub-run, yet finding such very efficiently when they exist.
-
-I first learned about the galloping strategy in a related context; see:
-
- "Adaptive Set Intersections, Unions, and Differences" (2000)
- Erik D. Demaine, Alejandro López-Ortiz, J. Ian Munro
-
-and its followup(s). An earlier paper called the same strategy
-"exponential search":
-
- "Optimistic Sorting and Information Theoretic Complexity"
- Peter McIlroy
- SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), pp
- 467-474, Austin, Texas, 25-27 January 1993.
-
-and it probably dates back to an earlier paper by Bentley and Yao. The
-McIlroy paper in particular has good analysis of a mergesort that's
-probably strongly related to this one in its galloping strategy.
-
-
-Galloping with a Broken Leg
----------------------------
-So why don't we always gallop? Because it can lose, on two counts:
-
-1. While we're willing to endure small per-merge overheads, per-comparison
- overheads are a different story. Calling Yet Another Function per
- comparison is expensive, and gallop_left() and gallop_right() are
- too long-winded for sane inlining.
-
-2. Galloping can-- alas --require more comparisons than linear one-at-time
- search, depending on the data.
-
-#2 requires details. If A[0] belongs before B[0], galloping requires 1
-compare to determine that, same as linear search, except it costs more
-to call the gallop function. If A[0] belongs right before B[1], galloping
-requires 2 compares, again same as linear search. On the third compare,
-galloping checks A[0] against B[3], and if it's <=, requires one more
-compare to determine whether A[0] belongs at B[2] or B[3]. That's a total
-of 4 compares, but if A[0] does belong at B[2], linear search would have
-discovered that in only 3 compares, and that's a huge loss! Really. It's
-an increase of 33% in the number of compares needed, and comparisons are
-expensive in Python.
-
-index in B where # compares linear # gallop # binary gallop
-A[0] belongs search needs compares compares total
----------------- ----------------- -------- -------- ------
- 0 1 1 0 1
-
- 1 2 2 0 2
-
- 2 3 3 1 4
- 3 4 3 1 4
-
- 4 5 4 2 6
- 5 6 4 2 6
- 6 7 4 2 6
- 7 8 4 2 6
-
- 8 9 5 3 8
- 9 10 5 3 8
- 10 11 5 3 8
- 11 12 5 3 8
- ...
-
-In general, if A[0] belongs at B[i], linear search requires i+1 comparisons
-to determine that, and galloping a total of 2*floor(lg(i))+2 comparisons.
-The advantage of galloping is unbounded as i grows, but it doesn't win at
-all until i=6. Before then, it loses twice (at i=2 and i=4), and ties
-at the other values. At and after i=6, galloping always wins.
-
-We can't guess in advance when it's going to win, though, so we do one pair
-at a time until the evidence seems strong that galloping may pay. MIN_GALLOP
-is 7, and that's pretty strong evidence. However, if the data is random, it
-simply will trigger galloping mode purely by luck every now and again, and
-it's quite likely to hit one of the losing cases next. On the other hand,
-in cases like ~sort, galloping always pays, and MIN_GALLOP is larger than it
-"should be" then. So the MergeState struct keeps a min_gallop variable
-that merge_lo and merge_hi adjust: the longer we stay in galloping mode,
-the smaller min_gallop gets, making it easier to transition back to
-galloping mode (if we ever leave it in the current merge, and at the
-start of the next merge). But whenever the gallop loop doesn't pay,
-min_gallop is increased by one, making it harder to transition back
-to galloping mode (and again both within a merge and across merges). For
-random data, this all but eliminates the gallop penalty: min_gallop grows
-large enough that we almost never get into galloping mode. And for cases
-like ~sort, min_gallop can fall to as low as 1. This seems to work well,
-but in all it's a minor improvement over using a fixed MIN_GALLOP value.
-
-
-Galloping Complication
-----------------------
-The description above was for merge_lo. merge_hi has to merge "from the
-other end", and really needs to gallop starting at the last element in a run
-instead of the first. Galloping from the first still works, but does more
-comparisons than it should (this is significant -- I timed it both ways).
-For this reason, the gallop_left() and gallop_right() functions have a
-"hint" argument, which is the index at which galloping should begin. So
-galloping can actually start at any index, and proceed at offsets of 1, 3,
-7, 15, ... or -1, -3, -7, -15, ... from the starting index.
-
-In the code as I type it's always called with either 0 or n-1 (where n is
-the # of elements in a run). It's tempting to try to do something fancier,
-melding galloping with some form of interpolation search; for example, if
-we're merging a run of length 1 with a run of length 10000, index 5000 is
-probably a better guess at the final result than either 0 or 9999. But
-it's unclear how to generalize that intuition usefully, and merging of
-wildly unbalanced runs already enjoys excellent performance.
-
-~sort is a good example of when balanced runs could benefit from a better
-hint value: to the extent possible, this would like to use a starting
-offset equal to the previous value of acount/bcount. Doing so saves about
-10% of the compares in ~sort. However, doing so is also a mixed bag,
-hurting other cases.
-
-
-Comparing Average # of Compares on Random Arrays
-------------------------------------------------
-[NOTE: This was done when the new algorithm used about 0.1% more compares
- on random data than does its current incarnation.]
-
-Here list.sort() is samplesort, and list.msort() this sort:
-
-"""
-import random
-from time import clock as now
-
-def fill(n):
- from random import random
- return [random() for i in xrange(n)]
-
-def mycmp(x, y):
- global ncmp
- ncmp += 1
- return cmp(x, y)
-
-def timeit(values, method):
- global ncmp
- X = values[:]
- bound = getattr(X, method)
- ncmp = 0
- t1 = now()
- bound(mycmp)
- t2 = now()
- return t2-t1, ncmp
-
-format = "%5s %9.2f %11d"
-f2 = "%5s %9.2f %11.2f"
-
-def drive():
- count = sst = sscmp = mst = mscmp = nelts = 0
- while True:
- n = random.randrange(100000)
- nelts += n
- x = fill(n)
-
- t, c = timeit(x, 'sort')
- sst += t
- sscmp += c
-
- t, c = timeit(x, 'msort')
- mst += t
- mscmp += c
-
- count += 1
- if count % 10:
- continue
-
- print "count", count, "nelts", nelts
- print format % ("sort", sst, sscmp)
- print format % ("msort", mst, mscmp)
- print f2 % ("", (sst-mst)*1e2/mst, (sscmp-mscmp)*1e2/mscmp)
-
-drive()
-"""
-
-I ran this on Windows and kept using the computer lightly while it was
-running. time.clock() is wall-clock time on Windows, with better than
-microsecond resolution. samplesort started with a 1.52% #-of-comparisons
-disadvantage, fell quickly to 1.48%, and then fluctuated within that small
-range. Here's the last chunk of output before I killed the job:
-
-count 2630 nelts 130906543
- sort 6110.80 1937887573
-msort 6002.78 1909389381
- 1.80 1.49
-
-We've done nearly 2 billion comparisons apiece at Python speed there, and
-that's enough <wink>.
-
-For random arrays of size 2 (yes, there are only 2 interesting ones),
-samplesort has a 50%(!) comparison disadvantage. This is a consequence of
-samplesort special-casing at most one ascending run at the start, then
-falling back to the general case if it doesn't find an ascending run
-immediately. The consequence is that it ends up using two compares to sort
-[2, 1]. Gratifyingly, timsort doesn't do any special-casing, so had to be
-taught how to deal with mixtures of ascending and descending runs
-efficiently in all cases.
diff --git a/sys/src/cmd/python/Objects/longobject.c b/sys/src/cmd/python/Objects/longobject.c
deleted file mode 100644
index cb4900d9d..000000000
--- a/sys/src/cmd/python/Objects/longobject.c
+++ /dev/null
@@ -1,3458 +0,0 @@
-
-
-/* Long (arbitrary precision) integer object implementation */
-
-/* XXX The functional organization of this file is terrible */
-
-#include "Python.h"
-#include "longintrepr.h"
-
-#include <ctype.h>
-
-/* For long multiplication, use the O(N**2) school algorithm unless
- * both operands contain more than KARATSUBA_CUTOFF digits (this
- * being an internal Python long digit, in base BASE).
- */
-#define KARATSUBA_CUTOFF 70
-#define KARATSUBA_SQUARE_CUTOFF (2 * KARATSUBA_CUTOFF)
-
-/* For exponentiation, use the binary left-to-right algorithm
- * unless the exponent contains more than FIVEARY_CUTOFF digits.
- * In that case, do 5 bits at a time. The potential drawback is that
- * a table of 2**5 intermediate results is computed.
- */
-#define FIVEARY_CUTOFF 8
-
-#define ABS(x) ((x) < 0 ? -(x) : (x))
-
-#undef MIN
-#undef MAX
-#define MAX(x, y) ((x) < (y) ? (y) : (x))
-#define MIN(x, y) ((x) > (y) ? (y) : (x))
-
-/* Forward */
-static PyLongObject *long_normalize(PyLongObject *);
-static PyLongObject *mul1(PyLongObject *, wdigit);
-static PyLongObject *muladd1(PyLongObject *, wdigit, wdigit);
-static PyLongObject *divrem1(PyLongObject *, digit, digit *);
-static PyObject *long_format(PyObject *aa, int base, int addL);
-
-#define SIGCHECK(PyTryBlock) \
- if (--_Py_Ticker < 0) { \
- _Py_Ticker = _Py_CheckInterval; \
- if (PyErr_CheckSignals()) PyTryBlock \
- }
-
-/* Normalize (remove leading zeros from) a long int object.
- Doesn't attempt to free the storage--in most cases, due to the nature
- of the algorithms used, this could save at most be one word anyway. */
-
-static PyLongObject *
-long_normalize(register PyLongObject *v)
-{
- Py_ssize_t j = ABS(v->ob_size);
- Py_ssize_t i = j;
-
- while (i > 0 && v->ob_digit[i-1] == 0)
- --i;
- if (i != j)
- v->ob_size = (v->ob_size < 0) ? -(i) : i;
- return v;
-}
-
-/* Allocate a new long int object with size digits.
- Return NULL and set exception if we run out of memory. */
-
-PyLongObject *
-_PyLong_New(Py_ssize_t size)
-{
- if (size > PY_SSIZE_T_MAX) {
- PyErr_NoMemory();
- return NULL;
- }
- return PyObject_NEW_VAR(PyLongObject, &PyLong_Type, size);
-}
-
-PyObject *
-_PyLong_Copy(PyLongObject *src)
-{
- PyLongObject *result;
- Py_ssize_t i;
-
- assert(src != NULL);
- i = src->ob_size;
- if (i < 0)
- i = -(i);
- result = _PyLong_New(i);
- if (result != NULL) {
- result->ob_size = src->ob_size;
- while (--i >= 0)
- result->ob_digit[i] = src->ob_digit[i];
- }
- return (PyObject *)result;
-}
-
-/* Create a new long int object from a C long int */
-
-PyObject *
-PyLong_FromLong(long ival)
-{
- PyLongObject *v;
- unsigned long t; /* unsigned so >> doesn't propagate sign bit */
- int ndigits = 0;
- int negative = 0;
-
- if (ival < 0) {
- ival = -ival;
- negative = 1;
- }
-
- /* Count the number of Python digits.
- We used to pick 5 ("big enough for anything"), but that's a
- waste of time and space given that 5*15 = 75 bits are rarely
- needed. */
- t = (unsigned long)ival;
- while (t) {
- ++ndigits;
- t >>= SHIFT;
- }
- v = _PyLong_New(ndigits);
- if (v != NULL) {
- digit *p = v->ob_digit;
- v->ob_size = negative ? -ndigits : ndigits;
- t = (unsigned long)ival;
- while (t) {
- *p++ = (digit)(t & MASK);
- t >>= SHIFT;
- }
- }
- return (PyObject *)v;
-}
-
-/* Create a new long int object from a C unsigned long int */
-
-PyObject *
-PyLong_FromUnsignedLong(unsigned long ival)
-{
- PyLongObject *v;
- unsigned long t;
- int ndigits = 0;
-
- /* Count the number of Python digits. */
- t = (unsigned long)ival;
- while (t) {
- ++ndigits;
- t >>= SHIFT;
- }
- v = _PyLong_New(ndigits);
- if (v != NULL) {
- digit *p = v->ob_digit;
- v->ob_size = ndigits;
- while (ival) {
- *p++ = (digit)(ival & MASK);
- ival >>= SHIFT;
- }
- }
- return (PyObject *)v;
-}
-
-/* Create a new long int object from a C double */
-
-PyObject *
-PyLong_FromDouble(double dval)
-{
- PyLongObject *v;
- double frac;
- int i, ndig, expo, neg;
- neg = 0;
- if (Py_IS_INFINITY(dval)) {
- PyErr_SetString(PyExc_OverflowError,
- "cannot convert float infinity to long");
- return NULL;
- }
- if (dval < 0.0) {
- neg = 1;
- dval = -dval;
- }
- frac = frexp(dval, &expo); /* dval = frac*2**expo; 0.0 <= frac < 1.0 */
- if (expo <= 0)
- return PyLong_FromLong(0L);
- ndig = (expo-1) / SHIFT + 1; /* Number of 'digits' in result */
- v = _PyLong_New(ndig);
- if (v == NULL)
- return NULL;
- frac = ldexp(frac, (expo-1) % SHIFT + 1);
- for (i = ndig; --i >= 0; ) {
- long bits = (long)frac;
- v->ob_digit[i] = (digit) bits;
- frac = frac - (double)bits;
- frac = ldexp(frac, SHIFT);
- }
- if (neg)
- v->ob_size = -(v->ob_size);
- return (PyObject *)v;
-}
-
-/* Checking for overflow in PyLong_AsLong is a PITA since C doesn't define
- * anything about what happens when a signed integer operation overflows,
- * and some compilers think they're doing you a favor by being "clever"
- * then. The bit pattern for the largest postive signed long is
- * (unsigned long)LONG_MAX, and for the smallest negative signed long
- * it is abs(LONG_MIN), which we could write -(unsigned long)LONG_MIN.
- * However, some other compilers warn about applying unary minus to an
- * unsigned operand. Hence the weird "0-".
- */
-#define PY_ABS_LONG_MIN (0-(unsigned long)LONG_MIN)
-#define PY_ABS_SSIZE_T_MIN (0-(size_t)PY_SSIZE_T_MIN)
-
-/* Get a C long int from a long int object.
- Returns -1 and sets an error condition if overflow occurs. */
-
-long
-PyLong_AsLong(PyObject *vv)
-{
- /* This version by Tim Peters */
- register PyLongObject *v;
- unsigned long x, prev;
- Py_ssize_t i;
- int sign;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- if (vv != NULL && PyInt_Check(vv))
- return PyInt_AsLong(vv);
- PyErr_BadInternalCall();
- return -1;
- }
- v = (PyLongObject *)vv;
- i = v->ob_size;
- sign = 1;
- x = 0;
- if (i < 0) {
- sign = -1;
- i = -(i);
- }
- while (--i >= 0) {
- prev = x;
- x = (x << SHIFT) + v->ob_digit[i];
- if ((x >> SHIFT) != prev)
- goto overflow;
- }
- /* Haven't lost any bits, but casting to long requires extra care
- * (see comment above).
- */
- if (x <= (unsigned long)LONG_MAX) {
- return (long)x * sign;
- }
- else if (sign < 0 && x == PY_ABS_LONG_MIN) {
- return LONG_MIN;
- }
- /* else overflow */
-
- overflow:
- PyErr_SetString(PyExc_OverflowError,
- "long int too large to convert to int");
- return -1;
-}
-
-/* Get a Py_ssize_t from a long int object.
- Returns -1 and sets an error condition if overflow occurs. */
-
-Py_ssize_t
-_PyLong_AsSsize_t(PyObject *vv) {
- register PyLongObject *v;
- size_t x, prev;
- Py_ssize_t i;
- int sign;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- PyErr_BadInternalCall();
- return -1;
- }
- v = (PyLongObject *)vv;
- i = v->ob_size;
- sign = 1;
- x = 0;
- if (i < 0) {
- sign = -1;
- i = -(i);
- }
- while (--i >= 0) {
- prev = x;
- x = (x << SHIFT) + v->ob_digit[i];
- if ((x >> SHIFT) != prev)
- goto overflow;
- }
- /* Haven't lost any bits, but casting to a signed type requires
- * extra care (see comment above).
- */
- if (x <= (size_t)PY_SSIZE_T_MAX) {
- return (Py_ssize_t)x * sign;
- }
- else if (sign < 0 && x == PY_ABS_SSIZE_T_MIN) {
- return PY_SSIZE_T_MIN;
- }
- /* else overflow */
-
- overflow:
- PyErr_SetString(PyExc_OverflowError,
- "long int too large to convert to int");
- return -1;
-}
-
-/* Get a C unsigned long int from a long int object.
- Returns -1 and sets an error condition if overflow occurs. */
-
-unsigned long
-PyLong_AsUnsignedLong(PyObject *vv)
-{
- register PyLongObject *v;
- unsigned long x, prev;
- Py_ssize_t i;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- if (vv != NULL && PyInt_Check(vv)) {
- long val = PyInt_AsLong(vv);
- if (val < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "can't convert negative value to unsigned long");
- return (unsigned long) -1;
- }
- return val;
- }
- PyErr_BadInternalCall();
- return (unsigned long) -1;
- }
- v = (PyLongObject *)vv;
- i = v->ob_size;
- x = 0;
- if (i < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "can't convert negative value to unsigned long");
- return (unsigned long) -1;
- }
- while (--i >= 0) {
- prev = x;
- x = (x << SHIFT) + v->ob_digit[i];
- if ((x >> SHIFT) != prev) {
- PyErr_SetString(PyExc_OverflowError,
- "long int too large to convert");
- return (unsigned long) -1;
- }
- }
- return x;
-}
-
-/* Get a C unsigned long int from a long int object, ignoring the high bits.
- Returns -1 and sets an error condition if an error occurs. */
-
-unsigned long
-PyLong_AsUnsignedLongMask(PyObject *vv)
-{
- register PyLongObject *v;
- unsigned long x;
- Py_ssize_t i;
- int sign;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- if (vv != NULL && PyInt_Check(vv))
- return PyInt_AsUnsignedLongMask(vv);
- PyErr_BadInternalCall();
- return (unsigned long) -1;
- }
- v = (PyLongObject *)vv;
- i = v->ob_size;
- sign = 1;
- x = 0;
- if (i < 0) {
- sign = -1;
- i = -i;
- }
- while (--i >= 0) {
- x = (x << SHIFT) + v->ob_digit[i];
- }
- return x * sign;
-}
-
-int
-_PyLong_Sign(PyObject *vv)
-{
- PyLongObject *v = (PyLongObject *)vv;
-
- assert(v != NULL);
- assert(PyLong_Check(v));
-
- return v->ob_size == 0 ? 0 : (v->ob_size < 0 ? -1 : 1);
-}
-
-size_t
-_PyLong_NumBits(PyObject *vv)
-{
- PyLongObject *v = (PyLongObject *)vv;
- size_t result = 0;
- Py_ssize_t ndigits;
-
- assert(v != NULL);
- assert(PyLong_Check(v));
- ndigits = ABS(v->ob_size);
- assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
- if (ndigits > 0) {
- digit msd = v->ob_digit[ndigits - 1];
-
- result = (ndigits - 1) * SHIFT;
- if (result / SHIFT != (size_t)(ndigits - 1))
- goto Overflow;
- do {
- ++result;
- if (result == 0)
- goto Overflow;
- msd >>= 1;
- } while (msd);
- }
- return result;
-
-Overflow:
- PyErr_SetString(PyExc_OverflowError, "long has too many bits "
- "to express in a platform size_t");
- return (size_t)-1;
-}
-
-PyObject *
-_PyLong_FromByteArray(const unsigned char* bytes, size_t n,
- int little_endian, int is_signed)
-{
- const unsigned char* pstartbyte;/* LSB of bytes */
- int incr; /* direction to move pstartbyte */
- const unsigned char* pendbyte; /* MSB of bytes */
- size_t numsignificantbytes; /* number of bytes that matter */
- size_t ndigits; /* number of Python long digits */
- PyLongObject* v; /* result */
- int idigit = 0; /* next free index in v->ob_digit */
-
- if (n == 0)
- return PyLong_FromLong(0L);
-
- if (little_endian) {
- pstartbyte = bytes;
- pendbyte = bytes + n - 1;
- incr = 1;
- }
- else {
- pstartbyte = bytes + n - 1;
- pendbyte = bytes;
- incr = -1;
- }
-
- if (is_signed)
- is_signed = *pendbyte >= 0x80;
-
- /* Compute numsignificantbytes. This consists of finding the most
- significant byte. Leading 0 bytes are insignficant if the number
- is positive, and leading 0xff bytes if negative. */
- {
- size_t i;
- const unsigned char* p = pendbyte;
- const int pincr = -incr; /* search MSB to LSB */
- const unsigned char insignficant = is_signed ? 0xff : 0x00;
-
- for (i = 0; i < n; ++i, p += pincr) {
- if (*p != insignficant)
- break;
- }
- numsignificantbytes = n - i;
- /* 2's-comp is a bit tricky here, e.g. 0xff00 == -0x0100, so
- actually has 2 significant bytes. OTOH, 0xff0001 ==
- -0x00ffff, so we wouldn't *need* to bump it there; but we
- do for 0xffff = -0x0001. To be safe without bothering to
- check every case, bump it regardless. */
- if (is_signed && numsignificantbytes < n)
- ++numsignificantbytes;
- }
-
- /* How many Python long digits do we need? We have
- 8*numsignificantbytes bits, and each Python long digit has SHIFT
- bits, so it's the ceiling of the quotient. */
- ndigits = (numsignificantbytes * 8 + SHIFT - 1) / SHIFT;
- if (ndigits > (size_t)INT_MAX)
- return PyErr_NoMemory();
- v = _PyLong_New((int)ndigits);
- if (v == NULL)
- return NULL;
-
- /* Copy the bits over. The tricky parts are computing 2's-comp on
- the fly for signed numbers, and dealing with the mismatch between
- 8-bit bytes and (probably) 15-bit Python digits.*/
- {
- size_t i;
- twodigits carry = 1; /* for 2's-comp calculation */
- twodigits accum = 0; /* sliding register */
- unsigned int accumbits = 0; /* number of bits in accum */
- const unsigned char* p = pstartbyte;
-
- for (i = 0; i < numsignificantbytes; ++i, p += incr) {
- twodigits thisbyte = *p;
- /* Compute correction for 2's comp, if needed. */
- if (is_signed) {
- thisbyte = (0xff ^ thisbyte) + carry;
- carry = thisbyte >> 8;
- thisbyte &= 0xff;
- }
- /* Because we're going LSB to MSB, thisbyte is
- more significant than what's already in accum,
- so needs to be prepended to accum. */
- accum |= thisbyte << accumbits;
- accumbits += 8;
- if (accumbits >= SHIFT) {
- /* There's enough to fill a Python digit. */
- assert(idigit < (int)ndigits);
- v->ob_digit[idigit] = (digit)(accum & MASK);
- ++idigit;
- accum >>= SHIFT;
- accumbits -= SHIFT;
- assert(accumbits < SHIFT);
- }
- }
- assert(accumbits < SHIFT);
- if (accumbits) {
- assert(idigit < (int)ndigits);
- v->ob_digit[idigit] = (digit)accum;
- ++idigit;
- }
- }
-
- v->ob_size = is_signed ? -idigit : idigit;
- return (PyObject *)long_normalize(v);
-}
-
-int
-_PyLong_AsByteArray(PyLongObject* v,
- unsigned char* bytes, size_t n,
- int little_endian, int is_signed)
-{
- int i; /* index into v->ob_digit */
- Py_ssize_t ndigits; /* |v->ob_size| */
- twodigits accum; /* sliding register */
- unsigned int accumbits; /* # bits in accum */
- int do_twos_comp; /* store 2's-comp? is_signed and v < 0 */
- twodigits carry; /* for computing 2's-comp */
- size_t j; /* # bytes filled */
- unsigned char* p; /* pointer to next byte in bytes */
- int pincr; /* direction to move p */
-
- assert(v != NULL && PyLong_Check(v));
-
- if (v->ob_size < 0) {
- ndigits = -(v->ob_size);
- if (!is_signed) {
- PyErr_SetString(PyExc_TypeError,
- "can't convert negative long to unsigned");
- return -1;
- }
- do_twos_comp = 1;
- }
- else {
- ndigits = v->ob_size;
- do_twos_comp = 0;
- }
-
- if (little_endian) {
- p = bytes;
- pincr = 1;
- }
- else {
- p = bytes + n - 1;
- pincr = -1;
- }
-
- /* Copy over all the Python digits.
- It's crucial that every Python digit except for the MSD contribute
- exactly SHIFT bits to the total, so first assert that the long is
- normalized. */
- assert(ndigits == 0 || v->ob_digit[ndigits - 1] != 0);
- j = 0;
- accum = 0;
- accumbits = 0;
- carry = do_twos_comp ? 1 : 0;
- for (i = 0; i < ndigits; ++i) {
- twodigits thisdigit = v->ob_digit[i];
- if (do_twos_comp) {
- thisdigit = (thisdigit ^ MASK) + carry;
- carry = thisdigit >> SHIFT;
- thisdigit &= MASK;
- }
- /* Because we're going LSB to MSB, thisdigit is more
- significant than what's already in accum, so needs to be
- prepended to accum. */
- accum |= thisdigit << accumbits;
- accumbits += SHIFT;
-
- /* The most-significant digit may be (probably is) at least
- partly empty. */
- if (i == ndigits - 1) {
- /* Count # of sign bits -- they needn't be stored,
- * although for signed conversion we need later to
- * make sure at least one sign bit gets stored.
- * First shift conceptual sign bit to real sign bit.
- */
- stwodigits s = (stwodigits)(thisdigit <<
- (8*sizeof(stwodigits) - SHIFT));
- unsigned int nsignbits = 0;
- while ((s < 0) == do_twos_comp && nsignbits < SHIFT) {
- ++nsignbits;
- s <<= 1;
- }
- accumbits -= nsignbits;
- }
-
- /* Store as many bytes as possible. */
- while (accumbits >= 8) {
- if (j >= n)
- goto Overflow;
- ++j;
- *p = (unsigned char)(accum & 0xff);
- p += pincr;
- accumbits -= 8;
- accum >>= 8;
- }
- }
-
- /* Store the straggler (if any). */
- assert(accumbits < 8);
- assert(carry == 0); /* else do_twos_comp and *every* digit was 0 */
- if (accumbits > 0) {
- if (j >= n)
- goto Overflow;
- ++j;
- if (do_twos_comp) {
- /* Fill leading bits of the byte with sign bits
- (appropriately pretending that the long had an
- infinite supply of sign bits). */
- accum |= (~(twodigits)0) << accumbits;
- }
- *p = (unsigned char)(accum & 0xff);
- p += pincr;
- }
- else if (j == n && n > 0 && is_signed) {
- /* The main loop filled the byte array exactly, so the code
- just above didn't get to ensure there's a sign bit, and the
- loop below wouldn't add one either. Make sure a sign bit
- exists. */
- unsigned char msb = *(p - pincr);
- int sign_bit_set = msb >= 0x80;
- assert(accumbits == 0);
- if (sign_bit_set == do_twos_comp)
- return 0;
- else
- goto Overflow;
- }
-
- /* Fill remaining bytes with copies of the sign bit. */
- {
- unsigned char signbyte = do_twos_comp ? 0xffU : 0U;
- for ( ; j < n; ++j, p += pincr)
- *p = signbyte;
- }
-
- return 0;
-
-Overflow:
- PyErr_SetString(PyExc_OverflowError, "long too big to convert");
- return -1;
-
-}
-
-double
-_PyLong_AsScaledDouble(PyObject *vv, int *exponent)
-{
-/* NBITS_WANTED should be > the number of bits in a double's precision,
- but small enough so that 2**NBITS_WANTED is within the normal double
- range. nbitsneeded is set to 1 less than that because the most-significant
- Python digit contains at least 1 significant bit, but we don't want to
- bother counting them (catering to the worst case cheaply).
-
- 57 is one more than VAX-D double precision; I (Tim) don't know of a double
- format with more precision than that; it's 1 larger so that we add in at
- least one round bit to stand in for the ignored least-significant bits.
-*/
-#define NBITS_WANTED 57
- PyLongObject *v;
- double x;
- const double multiplier = (double)(1L << SHIFT);
- Py_ssize_t i;
- int sign;
- int nbitsneeded;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- PyErr_BadInternalCall();
- return -1;
- }
- v = (PyLongObject *)vv;
- i = v->ob_size;
- sign = 1;
- if (i < 0) {
- sign = -1;
- i = -(i);
- }
- else if (i == 0) {
- *exponent = 0;
- return 0.0;
- }
- --i;
- x = (double)v->ob_digit[i];
- nbitsneeded = NBITS_WANTED - 1;
- /* Invariant: i Python digits remain unaccounted for. */
- while (i > 0 && nbitsneeded > 0) {
- --i;
- x = x * multiplier + (double)v->ob_digit[i];
- nbitsneeded -= SHIFT;
- }
- /* There are i digits we didn't shift in. Pretending they're all
- zeroes, the true value is x * 2**(i*SHIFT). */
- *exponent = i;
- assert(x > 0.0);
- return x * sign;
-#undef NBITS_WANTED
-}
-
-/* Get a C double from a long int object. */
-
-double
-PyLong_AsDouble(PyObject *vv)
-{
- int e = -1;
- double x;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- PyErr_BadInternalCall();
- return -1;
- }
- x = _PyLong_AsScaledDouble(vv, &e);
- if (x == -1.0 && PyErr_Occurred())
- return -1.0;
- /* 'e' initialized to -1 to silence gcc-4.0.x, but it should be
- set correctly after a successful _PyLong_AsScaledDouble() call */
- assert(e >= 0);
- if (e > INT_MAX / SHIFT)
- goto overflow;
- errno = 0;
- x = ldexp(x, e * SHIFT);
- if (Py_OVERFLOWED(x))
- goto overflow;
- return x;
-
-overflow:
- PyErr_SetString(PyExc_OverflowError,
- "long int too large to convert to float");
- return -1.0;
-}
-
-/* Create a new long (or int) object from a C pointer */
-
-PyObject *
-PyLong_FromVoidPtr(void *p)
-{
-#if SIZEOF_VOID_P <= SIZEOF_LONG
- if ((long)p < 0)
- return PyLong_FromUnsignedLong((unsigned long)p);
- return PyInt_FromLong((long)p);
-#else
-
-#ifndef HAVE_LONG_LONG
-# error "PyLong_FromVoidPtr: sizeof(void*) > sizeof(long), but no long long"
-#endif
-#if SIZEOF_LONG_LONG < SIZEOF_VOID_P
-# error "PyLong_FromVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
-#endif
- /* optimize null pointers */
- if (p == NULL)
- return PyInt_FromLong(0);
- return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)p);
-
-#endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
-}
-
-/* Get a C pointer from a long object (or an int object in some cases) */
-
-void *
-PyLong_AsVoidPtr(PyObject *vv)
-{
- /* This function will allow int or long objects. If vv is neither,
- then the PyLong_AsLong*() functions will raise the exception:
- PyExc_SystemError, "bad argument to internal function"
- */
-#if SIZEOF_VOID_P <= SIZEOF_LONG
- long x;
-
- if (PyInt_Check(vv))
- x = PyInt_AS_LONG(vv);
- else if (PyLong_Check(vv) && _PyLong_Sign(vv) < 0)
- x = PyLong_AsLong(vv);
- else
- x = PyLong_AsUnsignedLong(vv);
-#else
-
-#ifndef HAVE_LONG_LONG
-# error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long"
-#endif
-#if SIZEOF_LONG_LONG < SIZEOF_VOID_P
-# error "PyLong_AsVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
-#endif
- PY_LONG_LONG x;
-
- if (PyInt_Check(vv))
- x = PyInt_AS_LONG(vv);
- else if (PyLong_Check(vv) && _PyLong_Sign(vv) < 0)
- x = PyLong_AsLongLong(vv);
- else
- x = PyLong_AsUnsignedLongLong(vv);
-
-#endif /* SIZEOF_VOID_P <= SIZEOF_LONG */
-
- if (x == -1 && PyErr_Occurred())
- return NULL;
- return (void *)x;
-}
-
-#ifdef HAVE_LONG_LONG
-
-/* Initial PY_LONG_LONG support by Chris Herborth (chrish@qnx.com), later
- * rewritten to use the newer PyLong_{As,From}ByteArray API.
- */
-
-#define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one
-
-/* Create a new long int object from a C PY_LONG_LONG int. */
-
-PyObject *
-PyLong_FromLongLong(PY_LONG_LONG ival)
-{
- PyLongObject *v;
- unsigned PY_LONG_LONG t; /* unsigned so >> doesn't propagate sign bit */
- int ndigits = 0;
- int negative = 0;
-
- if (ival < 0) {
- ival = -ival;
- negative = 1;
- }
-
- /* Count the number of Python digits.
- We used to pick 5 ("big enough for anything"), but that's a
- waste of time and space given that 5*15 = 75 bits are rarely
- needed. */
- t = (unsigned PY_LONG_LONG)ival;
- while (t) {
- ++ndigits;
- t >>= SHIFT;
- }
- v = _PyLong_New(ndigits);
- if (v != NULL) {
- digit *p = v->ob_digit;
- v->ob_size = negative ? -ndigits : ndigits;
- t = (unsigned PY_LONG_LONG)ival;
- while (t) {
- *p++ = (digit)(t & MASK);
- t >>= SHIFT;
- }
- }
- return (PyObject *)v;
-}
-
-/* Create a new long int object from a C unsigned PY_LONG_LONG int. */
-
-PyObject *
-PyLong_FromUnsignedLongLong(unsigned PY_LONG_LONG ival)
-{
- PyLongObject *v;
- unsigned PY_LONG_LONG t;
- int ndigits = 0;
-
- /* Count the number of Python digits. */
- t = (unsigned PY_LONG_LONG)ival;
- while (t) {
- ++ndigits;
- t >>= SHIFT;
- }
- v = _PyLong_New(ndigits);
- if (v != NULL) {
- digit *p = v->ob_digit;
- v->ob_size = ndigits;
- while (ival) {
- *p++ = (digit)(ival & MASK);
- ival >>= SHIFT;
- }
- }
- return (PyObject *)v;
-}
-
-/* Create a new long int object from a C Py_ssize_t. */
-
-PyObject *
-_PyLong_FromSsize_t(Py_ssize_t ival)
-{
- Py_ssize_t bytes = ival;
- int one = 1;
- return _PyLong_FromByteArray(
- (unsigned char *)&bytes,
- SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0);
-}
-
-/* Create a new long int object from a C size_t. */
-
-PyObject *
-_PyLong_FromSize_t(size_t ival)
-{
- size_t bytes = ival;
- int one = 1;
- return _PyLong_FromByteArray(
- (unsigned char *)&bytes,
- SIZEOF_SIZE_T, IS_LITTLE_ENDIAN, 0);
-}
-
-/* Get a C PY_LONG_LONG int from a long int object.
- Return -1 and set an error if overflow occurs. */
-
-PY_LONG_LONG
-PyLong_AsLongLong(PyObject *vv)
-{
- PY_LONG_LONG bytes;
- int one = 1;
- int res;
-
- if (vv == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (!PyLong_Check(vv)) {
- PyNumberMethods *nb;
- PyObject *io;
- if (PyInt_Check(vv))
- return (PY_LONG_LONG)PyInt_AsLong(vv);
- if ((nb = vv->ob_type->tp_as_number) == NULL ||
- nb->nb_int == NULL) {
- PyErr_SetString(PyExc_TypeError, "an integer is required");
- return -1;
- }
- io = (*nb->nb_int) (vv);
- if (io == NULL)
- return -1;
- if (PyInt_Check(io)) {
- bytes = PyInt_AsLong(io);
- Py_DECREF(io);
- return bytes;
- }
- if (PyLong_Check(io)) {
- bytes = PyLong_AsLongLong(io);
- Py_DECREF(io);
- return bytes;
- }
- Py_DECREF(io);
- PyErr_SetString(PyExc_TypeError, "integer conversion failed");
- return -1;
- }
-
- res = _PyLong_AsByteArray(
- (PyLongObject *)vv, (unsigned char *)&bytes,
- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 1);
-
- /* Plan 9 can't handle PY_LONG_LONG in ? : expressions */
- if (res < 0)
- return (PY_LONG_LONG)-1;
- else
- return bytes;
-}
-
-/* Get a C unsigned PY_LONG_LONG int from a long int object.
- Return -1 and set an error if overflow occurs. */
-
-unsigned PY_LONG_LONG
-PyLong_AsUnsignedLongLong(PyObject *vv)
-{
- unsigned PY_LONG_LONG bytes;
- int one = 1;
- int res;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- PyErr_BadInternalCall();
- return (unsigned PY_LONG_LONG)-1;
- }
-
- res = _PyLong_AsByteArray(
- (PyLongObject *)vv, (unsigned char *)&bytes,
- SIZEOF_LONG_LONG, IS_LITTLE_ENDIAN, 0);
-
- /* Plan 9 can't handle PY_LONG_LONG in ? : expressions */
- if (res < 0)
- return (unsigned PY_LONG_LONG)res;
- else
- return bytes;
-}
-
-/* Get a C unsigned long int from a long int object, ignoring the high bits.
- Returns -1 and sets an error condition if an error occurs. */
-
-unsigned PY_LONG_LONG
-PyLong_AsUnsignedLongLongMask(PyObject *vv)
-{
- register PyLongObject *v;
- unsigned PY_LONG_LONG x;
- Py_ssize_t i;
- int sign;
-
- if (vv == NULL || !PyLong_Check(vv)) {
- PyErr_BadInternalCall();
- return (unsigned long) -1;
- }
- v = (PyLongObject *)vv;
- i = v->ob_size;
- sign = 1;
- x = 0;
- if (i < 0) {
- sign = -1;
- i = -i;
- }
- while (--i >= 0) {
- x = (x << SHIFT) + v->ob_digit[i];
- }
- return x * sign;
-}
-#undef IS_LITTLE_ENDIAN
-
-#endif /* HAVE_LONG_LONG */
-
-
-static int
-convert_binop(PyObject *v, PyObject *w, PyLongObject **a, PyLongObject **b) {
- if (PyLong_Check(v)) {
- *a = (PyLongObject *) v;
- Py_INCREF(v);
- }
- else if (PyInt_Check(v)) {
- *a = (PyLongObject *) PyLong_FromLong(PyInt_AS_LONG(v));
- }
- else {
- return 0;
- }
- if (PyLong_Check(w)) {
- *b = (PyLongObject *) w;
- Py_INCREF(w);
- }
- else if (PyInt_Check(w)) {
- *b = (PyLongObject *) PyLong_FromLong(PyInt_AS_LONG(w));
- }
- else {
- Py_DECREF(*a);
- return 0;
- }
- return 1;
-}
-
-#define CONVERT_BINOP(v, w, a, b) \
- if (!convert_binop(v, w, a, b)) { \
- Py_INCREF(Py_NotImplemented); \
- return Py_NotImplemented; \
- }
-
-/* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n]
- * is modified in place, by adding y to it. Carries are propagated as far as
- * x[m-1], and the remaining carry (0 or 1) is returned.
- */
-static digit
-v_iadd(digit *x, Py_ssize_t m, digit *y, Py_ssize_t n)
-{
- int i;
- digit carry = 0;
-
- assert(m >= n);
- for (i = 0; i < n; ++i) {
- carry += x[i] + y[i];
- x[i] = carry & MASK;
- carry >>= SHIFT;
- assert((carry & 1) == carry);
- }
- for (; carry && i < m; ++i) {
- carry += x[i];
- x[i] = carry & MASK;
- carry >>= SHIFT;
- assert((carry & 1) == carry);
- }
- return carry;
-}
-
-/* x[0:m] and y[0:n] are digit vectors, LSD first, m >= n required. x[0:n]
- * is modified in place, by subtracting y from it. Borrows are propagated as
- * far as x[m-1], and the remaining borrow (0 or 1) is returned.
- */
-static digit
-v_isub(digit *x, Py_ssize_t m, digit *y, Py_ssize_t n)
-{
- int i;
- digit borrow = 0;
-
- assert(m >= n);
- for (i = 0; i < n; ++i) {
- borrow = x[i] - y[i] - borrow;
- x[i] = borrow & MASK;
- borrow >>= SHIFT;
- borrow &= 1; /* keep only 1 sign bit */
- }
- for (; borrow && i < m; ++i) {
- borrow = x[i] - borrow;
- x[i] = borrow & MASK;
- borrow >>= SHIFT;
- borrow &= 1;
- }
- return borrow;
-}
-
-/* Multiply by a single digit, ignoring the sign. */
-
-static PyLongObject *
-mul1(PyLongObject *a, wdigit n)
-{
- return muladd1(a, n, (digit)0);
-}
-
-/* Multiply by a single digit and add a single digit, ignoring the sign. */
-
-static PyLongObject *
-muladd1(PyLongObject *a, wdigit n, wdigit extra)
-{
- Py_ssize_t size_a = ABS(a->ob_size);
- PyLongObject *z = _PyLong_New(size_a+1);
- twodigits carry = extra;
- Py_ssize_t i;
-
- if (z == NULL)
- return NULL;
- for (i = 0; i < size_a; ++i) {
- carry += (twodigits)a->ob_digit[i] * n;
- z->ob_digit[i] = (digit) (carry & MASK);
- carry >>= SHIFT;
- }
- z->ob_digit[i] = (digit) carry;
- return long_normalize(z);
-}
-
-/* Divide long pin, w/ size digits, by non-zero digit n, storing quotient
- in pout, and returning the remainder. pin and pout point at the LSD.
- It's OK for pin == pout on entry, which saves oodles of mallocs/frees in
- long_format, but that should be done with great care since longs are
- immutable. */
-
-static digit
-inplace_divrem1(digit *pout, digit *pin, Py_ssize_t size, digit n)
-{
- twodigits rem = 0;
-
- assert(n > 0 && n <= MASK);
- pin += size;
- pout += size;
- while (--size >= 0) {
- digit hi;
- rem = (rem << SHIFT) + *--pin;
- *--pout = hi = (digit)(rem / n);
- rem -= hi * n;
- }
- return (digit)rem;
-}
-
-/* Divide a long integer by a digit, returning both the quotient
- (as function result) and the remainder (through *prem).
- The sign of a is ignored; n should not be zero. */
-
-static PyLongObject *
-divrem1(PyLongObject *a, digit n, digit *prem)
-{
- const Py_ssize_t size = ABS(a->ob_size);
- PyLongObject *z;
-
- assert(n > 0 && n <= MASK);
- z = _PyLong_New(size);
- if (z == NULL)
- return NULL;
- *prem = inplace_divrem1(z->ob_digit, a->ob_digit, size, n);
- return long_normalize(z);
-}
-
-/* Convert a long int object to a string, using a given conversion base.
- Return a string object.
- If base is 8 or 16, add the proper prefix '0' or '0x'. */
-
-static PyObject *
-long_format(PyObject *aa, int base, int addL)
-{
- register PyLongObject *a = (PyLongObject *)aa;
- PyStringObject *str;
- Py_ssize_t i, j, sz;
- Py_ssize_t size_a;
- char *p;
- int bits;
- char sign = '\0';
-
- if (a == NULL || !PyLong_Check(a)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- assert(base >= 2 && base <= 36);
- size_a = ABS(a->ob_size);
-
- /* Compute a rough upper bound for the length of the string */
- i = base;
- bits = 0;
- while (i > 1) {
- ++bits;
- i >>= 1;
- }
- i = 5 + (addL ? 1 : 0);
- j = size_a*SHIFT + bits-1;
- sz = i + j / bits;
- if (j / SHIFT < size_a || sz < i) {
- PyErr_SetString(PyExc_OverflowError,
- "long is too large to format");
- return NULL;
- }
- str = (PyStringObject *) PyString_FromStringAndSize((char *)0, sz);
- if (str == NULL)
- return NULL;
- p = PyString_AS_STRING(str) + sz;
- *p = '\0';
- if (addL)
- *--p = 'L';
- if (a->ob_size < 0)
- sign = '-';
-
- if (a->ob_size == 0) {
- *--p = '0';
- }
- else if ((base & (base - 1)) == 0) {
- /* JRH: special case for power-of-2 bases */
- twodigits accum = 0;
- int accumbits = 0; /* # of bits in accum */
- int basebits = 1; /* # of bits in base-1 */
- i = base;
- while ((i >>= 1) > 1)
- ++basebits;
-
- for (i = 0; i < size_a; ++i) {
- accum |= (twodigits)a->ob_digit[i] << accumbits;
- accumbits += SHIFT;
- assert(accumbits >= basebits);
- do {
- char cdigit = (char)(accum & (base - 1));
- cdigit += (cdigit < 10) ? '0' : 'a'-10;
- assert(p > PyString_AS_STRING(str));
- *--p = cdigit;
- accumbits -= basebits;
- accum >>= basebits;
- } while (i < size_a-1 ? accumbits >= basebits :
- accum > 0);
- }
- }
- else {
- /* Not 0, and base not a power of 2. Divide repeatedly by
- base, but for speed use the highest power of base that
- fits in a digit. */
- Py_ssize_t size = size_a;
- digit *pin = a->ob_digit;
- PyLongObject *scratch;
- /* powbasw <- largest power of base that fits in a digit. */
- digit powbase = base; /* powbase == base ** power */
- int power = 1;
- for (;;) {
- unsigned long newpow = powbase * (unsigned long)base;
- if (newpow >> SHIFT) /* doesn't fit in a digit */
- break;
- powbase = (digit)newpow;
- ++power;
- }
-
- /* Get a scratch area for repeated division. */
- scratch = _PyLong_New(size);
- if (scratch == NULL) {
- Py_DECREF(str);
- return NULL;
- }
-
- /* Repeatedly divide by powbase. */
- do {
- int ntostore = power;
- digit rem = inplace_divrem1(scratch->ob_digit,
- pin, size, powbase);
- pin = scratch->ob_digit; /* no need to use a again */
- if (pin[size - 1] == 0)
- --size;
- SIGCHECK({
- Py_DECREF(scratch);
- Py_DECREF(str);
- return NULL;
- })
-
- /* Break rem into digits. */
- assert(ntostore > 0);
- do {
- digit nextrem = (digit)(rem / base);
- char c = (char)(rem - nextrem * base);
- assert(p > PyString_AS_STRING(str));
- c += (c < 10) ? '0' : 'a'-10;
- *--p = c;
- rem = nextrem;
- --ntostore;
- /* Termination is a bit delicate: must not
- store leading zeroes, so must get out if
- remaining quotient and rem are both 0. */
- } while (ntostore && (size || rem));
- } while (size != 0);
- Py_DECREF(scratch);
- }
-
- if (base == 8) {
- if (size_a != 0)
- *--p = '0';
- }
- else if (base == 16) {
- *--p = 'x';
- *--p = '0';
- }
- else if (base != 10) {
- *--p = '#';
- *--p = '0' + base%10;
- if (base > 10)
- *--p = '0' + base/10;
- }
- if (sign)
- *--p = sign;
- if (p != PyString_AS_STRING(str)) {
- char *q = PyString_AS_STRING(str);
- assert(p > q);
- do {
- } while ((*q++ = *p++) != '\0');
- q--;
- _PyString_Resize((PyObject **)&str,
- (Py_ssize_t) (q - PyString_AS_STRING(str)));
- }
- return (PyObject *)str;
-}
-
-/* Table of digit values for 8-bit string -> integer conversion.
- * '0' maps to 0, ..., '9' maps to 9.
- * 'a' and 'A' map to 10, ..., 'z' and 'Z' map to 35.
- * All other indices map to 37.
- * Note that when converting a base B string, a char c is a legitimate
- * base B digit iff _PyLong_DigitValue[Py_CHARMASK(c)] < B.
- */
-int _PyLong_DigitValue[256] = {
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 37, 37, 37, 37, 37, 37,
- 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
- 37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
-};
-
-/* *str points to the first digit in a string of base `base` digits. base
- * is a power of 2 (2, 4, 8, 16, or 32). *str is set to point to the first
- * non-digit (which may be *str!). A normalized long is returned.
- * The point to this routine is that it takes time linear in the number of
- * string characters.
- */
-static PyLongObject *
-long_from_binary_base(char **str, int base)
-{
- char *p = *str;
- char *start = p;
- int bits_per_char;
- Py_ssize_t n;
- PyLongObject *z;
- twodigits accum;
- int bits_in_accum;
- digit *pdigit;
-
- assert(base >= 2 && base <= 32 && (base & (base - 1)) == 0);
- n = base;
- for (bits_per_char = -1; n; ++bits_per_char)
- n >>= 1;
- /* n <- total # of bits needed, while setting p to end-of-string */
- n = 0;
- while (_PyLong_DigitValue[Py_CHARMASK(*p)] < base)
- ++p;
- *str = p;
- /* n <- # of Python digits needed, = ceiling(n/SHIFT). */
- n = (p - start) * bits_per_char + SHIFT - 1;
- if (n / bits_per_char < p - start) {
- PyErr_SetString(PyExc_ValueError,
- "long string too large to convert");
- return NULL;
- }
- n = n / SHIFT;
- z = _PyLong_New(n);
- if (z == NULL)
- return NULL;
- /* Read string from right, and fill in long from left; i.e.,
- * from least to most significant in both.
- */
- accum = 0;
- bits_in_accum = 0;
- pdigit = z->ob_digit;
- while (--p >= start) {
- int k = _PyLong_DigitValue[Py_CHARMASK(*p)];
- assert(k >= 0 && k < base);
- accum |= (twodigits)(k << bits_in_accum);
- bits_in_accum += bits_per_char;
- if (bits_in_accum >= SHIFT) {
- *pdigit++ = (digit)(accum & MASK);
- assert(pdigit - z->ob_digit <= (int)n);
- accum >>= SHIFT;
- bits_in_accum -= SHIFT;
- assert(bits_in_accum < SHIFT);
- }
- }
- if (bits_in_accum) {
- assert(bits_in_accum <= SHIFT);
- *pdigit++ = (digit)accum;
- assert(pdigit - z->ob_digit <= (int)n);
- }
- while (pdigit - z->ob_digit < n)
- *pdigit++ = 0;
- return long_normalize(z);
-}
-
-PyObject *
-PyLong_FromString(char *str, char **pend, int base)
-{
- int sign = 1;
- char *start, *orig_str = str;
- PyLongObject *z;
- PyObject *strobj, *strrepr;
- Py_ssize_t slen;
-
- if ((base != 0 && base < 2) || base > 36) {
- PyErr_SetString(PyExc_ValueError,
- "long() arg 2 must be >= 2 and <= 36");
- return NULL;
- }
- while (*str != '\0' && isspace(Py_CHARMASK(*str)))
- str++;
- if (*str == '+')
- ++str;
- else if (*str == '-') {
- ++str;
- sign = -1;
- }
- while (*str != '\0' && isspace(Py_CHARMASK(*str)))
- str++;
- if (base == 0) {
- if (str[0] != '0')
- base = 10;
- else if (str[1] == 'x' || str[1] == 'X')
- base = 16;
- else
- base = 8;
- }
- if (base == 16 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
- str += 2;
-
- start = str;
- if ((base & (base - 1)) == 0)
- z = long_from_binary_base(&str, base);
- else {
-/***
-Binary bases can be converted in time linear in the number of digits, because
-Python's representation base is binary. Other bases (including decimal!) use
-the simple quadratic-time algorithm below, complicated by some speed tricks.
-
-First some math: the largest integer that can be expressed in N base-B digits
-is B**N-1. Consequently, if we have an N-digit input in base B, the worst-
-case number of Python digits needed to hold it is the smallest integer n s.t.
-
- BASE**n-1 >= B**N-1 [or, adding 1 to both sides]
- BASE**n >= B**N [taking logs to base BASE]
- n >= log(B**N)/log(BASE) = N * log(B)/log(BASE)
-
-The static array log_base_BASE[base] == log(base)/log(BASE) so we can compute
-this quickly. A Python long with that much space is reserved near the start,
-and the result is computed into it.
-
-The input string is actually treated as being in base base**i (i.e., i digits
-are processed at a time), where two more static arrays hold:
-
- convwidth_base[base] = the largest integer i such that base**i <= BASE
- convmultmax_base[base] = base ** convwidth_base[base]
-
-The first of these is the largest i such that i consecutive input digits
-must fit in a single Python digit. The second is effectively the input
-base we're really using.
-
-Viewing the input as a sequence <c0, c1, ..., c_n-1> of digits in base
-convmultmax_base[base], the result is "simply"
-
- (((c0*B + c1)*B + c2)*B + c3)*B + ... ))) + c_n-1
-
-where B = convmultmax_base[base].
-
-Error analysis: as above, the number of Python digits `n` needed is worst-
-case
-
- n >= N * log(B)/log(BASE)
-
-where `N` is the number of input digits in base `B`. This is computed via
-
- size_z = (Py_ssize_t)((scan - str) * log_base_BASE[base]) + 1;
-
-below. Two numeric concerns are how much space this can waste, and whether
-the computed result can be too small. To be concrete, assume BASE = 2**15,
-which is the default (and it's unlikely anyone changes that).
-
-Waste isn't a problem: provided the first input digit isn't 0, the difference
-between the worst-case input with N digits and the smallest input with N
-digits is about a factor of B, but B is small compared to BASE so at most
-one allocated Python digit can remain unused on that count. If
-N*log(B)/log(BASE) is mathematically an exact integer, then truncating that
-and adding 1 returns a result 1 larger than necessary. However, that can't
-happen: whenever B is a power of 2, long_from_binary_base() is called
-instead, and it's impossible for B**i to be an integer power of 2**15 when
-B is not a power of 2 (i.e., it's impossible for N*log(B)/log(BASE) to be
-an exact integer when B is not a power of 2, since B**i has a prime factor
-other than 2 in that case, but (2**15)**j's only prime factor is 2).
-
-The computed result can be too small if the true value of N*log(B)/log(BASE)
-is a little bit larger than an exact integer, but due to roundoff errors (in
-computing log(B), log(BASE), their quotient, and/or multiplying that by N)
-yields a numeric result a little less than that integer. Unfortunately, "how
-close can a transcendental function get to an integer over some range?"
-questions are generally theoretically intractable. Computer analysis via
-continued fractions is practical: expand log(B)/log(BASE) via continued
-fractions, giving a sequence i/j of "the best" rational approximations. Then
-j*log(B)/log(BASE) is approximately equal to (the integer) i. This shows that
-we can get very close to being in trouble, but very rarely. For example,
-76573 is a denominator in one of the continued-fraction approximations to
-log(10)/log(2**15), and indeed:
-
- >>> log(10)/log(2**15)*76573
- 16958.000000654003
-
-is very close to an integer. If we were working with IEEE single-precision,
-rounding errors could kill us. Finding worst cases in IEEE double-precision
-requires better-than-double-precision log() functions, and Tim didn't bother.
-Instead the code checks to see whether the allocated space is enough as each
-new Python digit is added, and copies the whole thing to a larger long if not.
-This should happen extremely rarely, and in fact I don't have a test case
-that triggers it(!). Instead the code was tested by artificially allocating
-just 1 digit at the start, so that the copying code was exercised for every
-digit beyond the first.
-***/
- register twodigits c; /* current input character */
- Py_ssize_t size_z;
- int i;
- int convwidth;
- twodigits convmultmax, convmult;
- digit *pz, *pzstop;
- char* scan;
-
- static double log_base_BASE[37] = {0.0e0,};
- static int convwidth_base[37] = {0,};
- static twodigits convmultmax_base[37] = {0,};
-
- if (log_base_BASE[base] == 0.0) {
- twodigits convmax = base;
- int i = 1;
-
- log_base_BASE[base] = log((double)base) /
- log((double)BASE);
- for (;;) {
- twodigits next = convmax * base;
- if (next > BASE)
- break;
- convmax = next;
- ++i;
- }
- convmultmax_base[base] = convmax;
- assert(i > 0);
- convwidth_base[base] = i;
- }
-
- /* Find length of the string of numeric characters. */
- scan = str;
- while (_PyLong_DigitValue[Py_CHARMASK(*scan)] < base)
- ++scan;
-
- /* Create a long object that can contain the largest possible
- * integer with this base and length. Note that there's no
- * need to initialize z->ob_digit -- no slot is read up before
- * being stored into.
- */
- size_z = (Py_ssize_t)((scan - str) * log_base_BASE[base]) + 1;
- /* Uncomment next line to test exceedingly rare copy code */
- /* size_z = 1; */
- assert(size_z > 0);
- z = _PyLong_New(size_z);
- if (z == NULL)
- return NULL;
- z->ob_size = 0;
-
- /* `convwidth` consecutive input digits are treated as a single
- * digit in base `convmultmax`.
- */
- convwidth = convwidth_base[base];
- convmultmax = convmultmax_base[base];
-
- /* Work ;-) */
- while (str < scan) {
- /* grab up to convwidth digits from the input string */
- c = (digit)_PyLong_DigitValue[Py_CHARMASK(*str++)];
- for (i = 1; i < convwidth && str != scan; ++i, ++str) {
- c = (twodigits)(c * base +
- _PyLong_DigitValue[Py_CHARMASK(*str)]);
- assert(c < BASE);
- }
-
- convmult = convmultmax;
- /* Calculate the shift only if we couldn't get
- * convwidth digits.
- */
- if (i != convwidth) {
- convmult = base;
- for ( ; i > 1; --i)
- convmult *= base;
- }
-
- /* Multiply z by convmult, and add c. */
- pz = z->ob_digit;
- pzstop = pz + z->ob_size;
- for (; pz < pzstop; ++pz) {
- c += (twodigits)*pz * convmult;
- *pz = (digit)(c & MASK);
- c >>= SHIFT;
- }
- /* carry off the current end? */
- if (c) {
- assert(c < BASE);
- if (z->ob_size < size_z) {
- *pz = (digit)c;
- ++z->ob_size;
- }
- else {
- PyLongObject *tmp;
- /* Extremely rare. Get more space. */
- assert(z->ob_size == size_z);
- tmp = _PyLong_New(size_z + 1);
- if (tmp == NULL) {
- Py_DECREF(z);
- return NULL;
- }
- memcpy(tmp->ob_digit,
- z->ob_digit,
- sizeof(digit) * size_z);
- Py_DECREF(z);
- z = tmp;
- z->ob_digit[size_z] = (digit)c;
- ++size_z;
- }
- }
- }
- }
- if (z == NULL)
- return NULL;
- if (str == start)
- goto onError;
- if (sign < 0)
- z->ob_size = -(z->ob_size);
- if (*str == 'L' || *str == 'l')
- str++;
- while (*str && isspace(Py_CHARMASK(*str)))
- str++;
- if (*str != '\0')
- goto onError;
- if (pend)
- *pend = str;
- return (PyObject *) z;
-
- onError:
- Py_XDECREF(z);
- slen = strlen(orig_str) < 200 ? strlen(orig_str) : 200;
- strobj = PyString_FromStringAndSize(orig_str, slen);
- if (strobj == NULL)
- return NULL;
- strrepr = PyObject_Repr(strobj);
- Py_DECREF(strobj);
- if (strrepr == NULL)
- return NULL;
- PyErr_Format(PyExc_ValueError,
- "invalid literal for long() with base %d: %s",
- base, PyString_AS_STRING(strrepr));
- Py_DECREF(strrepr);
- return NULL;
-}
-
-#ifdef Py_USING_UNICODE
-PyObject *
-PyLong_FromUnicode(Py_UNICODE *u, Py_ssize_t length, int base)
-{
- PyObject *result;
- char *buffer = (char *)PyMem_MALLOC(length+1);
-
- if (buffer == NULL)
- return NULL;
-
- if (PyUnicode_EncodeDecimal(u, length, buffer, NULL)) {
- PyMem_FREE(buffer);
- return NULL;
- }
- result = PyLong_FromString(buffer, NULL, base);
- PyMem_FREE(buffer);
- return result;
-}
-#endif
-
-/* forward */
-static PyLongObject *x_divrem
- (PyLongObject *, PyLongObject *, PyLongObject **);
-static PyObject *long_pos(PyLongObject *);
-static int long_divrem(PyLongObject *, PyLongObject *,
- PyLongObject **, PyLongObject **);
-
-/* Long division with remainder, top-level routine */
-
-static int
-long_divrem(PyLongObject *a, PyLongObject *b,
- PyLongObject **pdiv, PyLongObject **prem)
-{
- Py_ssize_t size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
- PyLongObject *z;
-
- if (size_b == 0) {
- PyErr_SetString(PyExc_ZeroDivisionError,
- "long division or modulo by zero");
- return -1;
- }
- if (size_a < size_b ||
- (size_a == size_b &&
- a->ob_digit[size_a-1] < b->ob_digit[size_b-1])) {
- /* |a| < |b|. */
- *pdiv = _PyLong_New(0);
- Py_INCREF(a);
- *prem = (PyLongObject *) a;
- return 0;
- }
- if (size_b == 1) {
- digit rem = 0;
- z = divrem1(a, b->ob_digit[0], &rem);
- if (z == NULL)
- return -1;
- *prem = (PyLongObject *) PyLong_FromLong((long)rem);
- }
- else {
- z = x_divrem(a, b, prem);
- if (z == NULL)
- return -1;
- }
- /* Set the signs.
- The quotient z has the sign of a*b;
- the remainder r has the sign of a,
- so a = b*z + r. */
- if ((a->ob_size < 0) != (b->ob_size < 0))
- z->ob_size = -(z->ob_size);
- if (a->ob_size < 0 && (*prem)->ob_size != 0)
- (*prem)->ob_size = -((*prem)->ob_size);
- *pdiv = z;
- return 0;
-}
-
-/* Unsigned long division with remainder -- the algorithm */
-
-static PyLongObject *
-x_divrem(PyLongObject *v1, PyLongObject *w1, PyLongObject **prem)
-{
- Py_ssize_t size_v = ABS(v1->ob_size), size_w = ABS(w1->ob_size);
- digit d = (digit) ((twodigits)BASE / (w1->ob_digit[size_w-1] + 1));
- PyLongObject *v = mul1(v1, d);
- PyLongObject *w = mul1(w1, d);
- PyLongObject *a;
- Py_ssize_t j, k;
-
- if (v == NULL || w == NULL) {
- Py_XDECREF(v);
- Py_XDECREF(w);
- return NULL;
- }
-
- assert(size_v >= size_w && size_w > 1); /* Assert checks by div() */
- assert(v->ob_refcnt == 1); /* Since v will be used as accumulator! */
- assert(size_w == ABS(w->ob_size)); /* That's how d was calculated */
-
- size_v = ABS(v->ob_size);
- k = size_v - size_w;
- a = _PyLong_New(k + 1);
-
- for (j = size_v; a != NULL && k >= 0; --j, --k) {
- digit vj = (j >= size_v) ? 0 : v->ob_digit[j];
- twodigits q;
- stwodigits carry = 0;
- int i;
-
- SIGCHECK({
- Py_DECREF(a);
- a = NULL;
- break;
- })
- if (vj == w->ob_digit[size_w-1])
- q = MASK;
- else
- q = (((twodigits)vj << SHIFT) + v->ob_digit[j-1]) /
- w->ob_digit[size_w-1];
-
- while (w->ob_digit[size_w-2]*q >
- ((
- ((twodigits)vj << SHIFT)
- + v->ob_digit[j-1]
- - q*w->ob_digit[size_w-1]
- ) << SHIFT)
- + v->ob_digit[j-2])
- --q;
-
- for (i = 0; i < size_w && i+k < size_v; ++i) {
- twodigits z = w->ob_digit[i] * q;
- digit zz = (digit) (z >> SHIFT);
- carry += v->ob_digit[i+k] - z
- + ((twodigits)zz << SHIFT);
- v->ob_digit[i+k] = (digit)(carry & MASK);
- carry = Py_ARITHMETIC_RIGHT_SHIFT(BASE_TWODIGITS_TYPE,
- carry, SHIFT);
- carry -= zz;
- }
-
- if (i+k < size_v) {
- carry += v->ob_digit[i+k];
- v->ob_digit[i+k] = 0;
- }
-
- if (carry == 0)
- a->ob_digit[k] = (digit) q;
- else {
- assert(carry == -1);
- a->ob_digit[k] = (digit) q-1;
- carry = 0;
- for (i = 0; i < size_w && i+k < size_v; ++i) {
- carry += v->ob_digit[i+k] + w->ob_digit[i];
- v->ob_digit[i+k] = (digit)(carry & MASK);
- carry = Py_ARITHMETIC_RIGHT_SHIFT(
- BASE_TWODIGITS_TYPE,
- carry, SHIFT);
- }
- }
- } /* for j, k */
-
- if (a == NULL)
- *prem = NULL;
- else {
- a = long_normalize(a);
- *prem = divrem1(v, d, &d);
- /* d receives the (unused) remainder */
- if (*prem == NULL) {
- Py_DECREF(a);
- a = NULL;
- }
- }
- Py_DECREF(v);
- Py_DECREF(w);
- return a;
-}
-
-/* Methods */
-
-static void
-long_dealloc(PyObject *v)
-{
- v->ob_type->tp_free(v);
-}
-
-static PyObject *
-long_repr(PyObject *v)
-{
- return long_format(v, 10, 1);
-}
-
-static PyObject *
-long_str(PyObject *v)
-{
- return long_format(v, 10, 0);
-}
-
-static int
-long_compare(PyLongObject *a, PyLongObject *b)
-{
- Py_ssize_t sign;
-
- if (a->ob_size != b->ob_size) {
- if (ABS(a->ob_size) == 0 && ABS(b->ob_size) == 0)
- sign = 0;
- else
- sign = a->ob_size - b->ob_size;
- }
- else {
- Py_ssize_t i = ABS(a->ob_size);
- while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
- ;
- if (i < 0)
- sign = 0;
- else {
- sign = (int)a->ob_digit[i] - (int)b->ob_digit[i];
- if (a->ob_size < 0)
- sign = -sign;
- }
- }
- return sign < 0 ? -1 : sign > 0 ? 1 : 0;
-}
-
-static long
-long_hash(PyLongObject *v)
-{
- long x;
- Py_ssize_t i;
- int sign;
-
- /* This is designed so that Python ints and longs with the
- same value hash to the same value, otherwise comparisons
- of mapping keys will turn out weird */
- i = v->ob_size;
- sign = 1;
- x = 0;
- if (i < 0) {
- sign = -1;
- i = -(i);
- }
-#define LONG_BIT_SHIFT (8*sizeof(long) - SHIFT)
- while (--i >= 0) {
- /* Force a native long #-bits (32 or 64) circular shift */
- x = ((x << SHIFT) & ~MASK) | ((x >> LONG_BIT_SHIFT) & MASK);
- x += v->ob_digit[i];
- }
-#undef LONG_BIT_SHIFT
- x = x * sign;
- if (x == -1)
- x = -2;
- return x;
-}
-
-
-/* Add the absolute values of two long integers. */
-
-static PyLongObject *
-x_add(PyLongObject *a, PyLongObject *b)
-{
- Py_ssize_t size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
- PyLongObject *z;
- int i;
- digit carry = 0;
-
- /* Ensure a is the larger of the two: */
- if (size_a < size_b) {
- { PyLongObject *temp = a; a = b; b = temp; }
- { Py_ssize_t size_temp = size_a;
- size_a = size_b;
- size_b = size_temp; }
- }
- z = _PyLong_New(size_a+1);
- if (z == NULL)
- return NULL;
- for (i = 0; i < size_b; ++i) {
- carry += a->ob_digit[i] + b->ob_digit[i];
- z->ob_digit[i] = carry & MASK;
- carry >>= SHIFT;
- }
- for (; i < size_a; ++i) {
- carry += a->ob_digit[i];
- z->ob_digit[i] = carry & MASK;
- carry >>= SHIFT;
- }
- z->ob_digit[i] = carry;
- return long_normalize(z);
-}
-
-/* Subtract the absolute values of two integers. */
-
-static PyLongObject *
-x_sub(PyLongObject *a, PyLongObject *b)
-{
- Py_ssize_t size_a = ABS(a->ob_size), size_b = ABS(b->ob_size);
- PyLongObject *z;
- Py_ssize_t i;
- int sign = 1;
- digit borrow = 0;
-
- /* Ensure a is the larger of the two: */
- if (size_a < size_b) {
- sign = -1;
- { PyLongObject *temp = a; a = b; b = temp; }
- { Py_ssize_t size_temp = size_a;
- size_a = size_b;
- size_b = size_temp; }
- }
- else if (size_a == size_b) {
- /* Find highest digit where a and b differ: */
- i = size_a;
- while (--i >= 0 && a->ob_digit[i] == b->ob_digit[i])
- ;
- if (i < 0)
- return _PyLong_New(0);
- if (a->ob_digit[i] < b->ob_digit[i]) {
- sign = -1;
- { PyLongObject *temp = a; a = b; b = temp; }
- }
- size_a = size_b = i+1;
- }
- z = _PyLong_New(size_a);
- if (z == NULL)
- return NULL;
- for (i = 0; i < size_b; ++i) {
- /* The following assumes unsigned arithmetic
- works module 2**N for some N>SHIFT. */
- borrow = a->ob_digit[i] - b->ob_digit[i] - borrow;
- z->ob_digit[i] = borrow & MASK;
- borrow >>= SHIFT;
- borrow &= 1; /* Keep only one sign bit */
- }
- for (; i < size_a; ++i) {
- borrow = a->ob_digit[i] - borrow;
- z->ob_digit[i] = borrow & MASK;
- borrow >>= SHIFT;
- borrow &= 1; /* Keep only one sign bit */
- }
- assert(borrow == 0);
- if (sign < 0)
- z->ob_size = -(z->ob_size);
- return long_normalize(z);
-}
-
-static PyObject *
-long_add(PyLongObject *v, PyLongObject *w)
-{
- PyLongObject *a, *b, *z;
-
- CONVERT_BINOP((PyObject *)v, (PyObject *)w, &a, &b);
-
- if (a->ob_size < 0) {
- if (b->ob_size < 0) {
- z = x_add(a, b);
- if (z != NULL && z->ob_size != 0)
- z->ob_size = -(z->ob_size);
- }
- else
- z = x_sub(b, a);
- }
- else {
- if (b->ob_size < 0)
- z = x_sub(a, b);
- else
- z = x_add(a, b);
- }
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *)z;
-}
-
-static PyObject *
-long_sub(PyLongObject *v, PyLongObject *w)
-{
- PyLongObject *a, *b, *z;
-
- CONVERT_BINOP((PyObject *)v, (PyObject *)w, &a, &b);
-
- if (a->ob_size < 0) {
- if (b->ob_size < 0)
- z = x_sub(a, b);
- else
- z = x_add(a, b);
- if (z != NULL && z->ob_size != 0)
- z->ob_size = -(z->ob_size);
- }
- else {
- if (b->ob_size < 0)
- z = x_add(a, b);
- else
- z = x_sub(a, b);
- }
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *)z;
-}
-
-/* Grade school multiplication, ignoring the signs.
- * Returns the absolute value of the product, or NULL if error.
- */
-static PyLongObject *
-x_mul(PyLongObject *a, PyLongObject *b)
-{
- PyLongObject *z;
- Py_ssize_t size_a = ABS(a->ob_size);
- Py_ssize_t size_b = ABS(b->ob_size);
- Py_ssize_t i;
-
- z = _PyLong_New(size_a + size_b);
- if (z == NULL)
- return NULL;
-
- memset(z->ob_digit, 0, z->ob_size * sizeof(digit));
- if (a == b) {
- /* Efficient squaring per HAC, Algorithm 14.16:
- * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
- * Gives slightly less than a 2x speedup when a == b,
- * via exploiting that each entry in the multiplication
- * pyramid appears twice (except for the size_a squares).
- */
- for (i = 0; i < size_a; ++i) {
- twodigits carry;
- twodigits f = a->ob_digit[i];
- digit *pz = z->ob_digit + (i << 1);
- digit *pa = a->ob_digit + i + 1;
- digit *paend = a->ob_digit + size_a;
-
- SIGCHECK({
- Py_DECREF(z);
- return NULL;
- })
-
- carry = *pz + f * f;
- *pz++ = (digit)(carry & MASK);
- carry >>= SHIFT;
- assert(carry <= MASK);
-
- /* Now f is added in twice in each column of the
- * pyramid it appears. Same as adding f<<1 once.
- */
- f <<= 1;
- while (pa < paend) {
- carry += *pz + *pa++ * f;
- *pz++ = (digit)(carry & MASK);
- carry >>= SHIFT;
- assert(carry <= (MASK << 1));
- }
- if (carry) {
- carry += *pz;
- *pz++ = (digit)(carry & MASK);
- carry >>= SHIFT;
- }
- if (carry)
- *pz += (digit)(carry & MASK);
- assert((carry >> SHIFT) == 0);
- }
- }
- else { /* a is not the same as b -- gradeschool long mult */
- for (i = 0; i < size_a; ++i) {
- twodigits carry = 0;
- twodigits f = a->ob_digit[i];
- digit *pz = z->ob_digit + i;
- digit *pb = b->ob_digit;
- digit *pbend = b->ob_digit + size_b;
-
- SIGCHECK({
- Py_DECREF(z);
- return NULL;
- })
-
- while (pb < pbend) {
- carry += *pz + *pb++ * f;
- *pz++ = (digit)(carry & MASK);
- carry >>= SHIFT;
- assert(carry <= MASK);
- }
- if (carry)
- *pz += (digit)(carry & MASK);
- assert((carry >> SHIFT) == 0);
- }
- }
- return long_normalize(z);
-}
-
-/* A helper for Karatsuba multiplication (k_mul).
- Takes a long "n" and an integer "size" representing the place to
- split, and sets low and high such that abs(n) == (high << size) + low,
- viewing the shift as being by digits. The sign bit is ignored, and
- the return values are >= 0.
- Returns 0 on success, -1 on failure.
-*/
-static int
-kmul_split(PyLongObject *n, Py_ssize_t size, PyLongObject **high, PyLongObject **low)
-{
- PyLongObject *hi, *lo;
- Py_ssize_t size_lo, size_hi;
- const Py_ssize_t size_n = ABS(n->ob_size);
-
- size_lo = MIN(size_n, size);
- size_hi = size_n - size_lo;
-
- if ((hi = _PyLong_New(size_hi)) == NULL)
- return -1;
- if ((lo = _PyLong_New(size_lo)) == NULL) {
- Py_DECREF(hi);
- return -1;
- }
-
- memcpy(lo->ob_digit, n->ob_digit, size_lo * sizeof(digit));
- memcpy(hi->ob_digit, n->ob_digit + size_lo, size_hi * sizeof(digit));
-
- *high = long_normalize(hi);
- *low = long_normalize(lo);
- return 0;
-}
-
-static PyLongObject *k_lopsided_mul(PyLongObject *a, PyLongObject *b);
-
-/* Karatsuba multiplication. Ignores the input signs, and returns the
- * absolute value of the product (or NULL if error).
- * See Knuth Vol. 2 Chapter 4.3.3 (Pp. 294-295).
- */
-static PyLongObject *
-k_mul(PyLongObject *a, PyLongObject *b)
-{
- Py_ssize_t asize = ABS(a->ob_size);
- Py_ssize_t bsize = ABS(b->ob_size);
- PyLongObject *ah = NULL;
- PyLongObject *al = NULL;
- PyLongObject *bh = NULL;
- PyLongObject *bl = NULL;
- PyLongObject *ret = NULL;
- PyLongObject *t1, *t2, *t3;
- Py_ssize_t shift; /* the number of digits we split off */
- Py_ssize_t i;
-
- /* (ah*X+al)(bh*X+bl) = ah*bh*X*X + (ah*bl + al*bh)*X + al*bl
- * Let k = (ah+al)*(bh+bl) = ah*bl + al*bh + ah*bh + al*bl
- * Then the original product is
- * ah*bh*X*X + (k - ah*bh - al*bl)*X + al*bl
- * By picking X to be a power of 2, "*X" is just shifting, and it's
- * been reduced to 3 multiplies on numbers half the size.
- */
-
- /* We want to split based on the larger number; fiddle so that b
- * is largest.
- */
- if (asize > bsize) {
- t1 = a;
- a = b;
- b = t1;
-
- i = asize;
- asize = bsize;
- bsize = i;
- }
-
- /* Use gradeschool math when either number is too small. */
- i = a == b ? KARATSUBA_SQUARE_CUTOFF : KARATSUBA_CUTOFF;
- if (asize <= i) {
- if (asize == 0)
- return _PyLong_New(0);
- else
- return x_mul(a, b);
- }
-
- /* If a is small compared to b, splitting on b gives a degenerate
- * case with ah==0, and Karatsuba may be (even much) less efficient
- * than "grade school" then. However, we can still win, by viewing
- * b as a string of "big digits", each of width a->ob_size. That
- * leads to a sequence of balanced calls to k_mul.
- */
- if (2 * asize <= bsize)
- return k_lopsided_mul(a, b);
-
- /* Split a & b into hi & lo pieces. */
- shift = bsize >> 1;
- if (kmul_split(a, shift, &ah, &al) < 0) goto fail;
- assert(ah->ob_size > 0); /* the split isn't degenerate */
-
- if (a == b) {
- bh = ah;
- bl = al;
- Py_INCREF(bh);
- Py_INCREF(bl);
- }
- else if (kmul_split(b, shift, &bh, &bl) < 0) goto fail;
-
- /* The plan:
- * 1. Allocate result space (asize + bsize digits: that's always
- * enough).
- * 2. Compute ah*bh, and copy into result at 2*shift.
- * 3. Compute al*bl, and copy into result at 0. Note that this
- * can't overlap with #2.
- * 4. Subtract al*bl from the result, starting at shift. This may
- * underflow (borrow out of the high digit), but we don't care:
- * we're effectively doing unsigned arithmetic mod
- * BASE**(sizea + sizeb), and so long as the *final* result fits,
- * borrows and carries out of the high digit can be ignored.
- * 5. Subtract ah*bh from the result, starting at shift.
- * 6. Compute (ah+al)*(bh+bl), and add it into the result starting
- * at shift.
- */
-
- /* 1. Allocate result space. */
- ret = _PyLong_New(asize + bsize);
- if (ret == NULL) goto fail;
-#ifdef Py_DEBUG
- /* Fill with trash, to catch reference to uninitialized digits. */
- memset(ret->ob_digit, 0xDF, ret->ob_size * sizeof(digit));
-#endif
-
- /* 2. t1 <- ah*bh, and copy into high digits of result. */
- if ((t1 = k_mul(ah, bh)) == NULL) goto fail;
- assert(t1->ob_size >= 0);
- assert(2*shift + t1->ob_size <= ret->ob_size);
- memcpy(ret->ob_digit + 2*shift, t1->ob_digit,
- t1->ob_size * sizeof(digit));
-
- /* Zero-out the digits higher than the ah*bh copy. */
- i = ret->ob_size - 2*shift - t1->ob_size;
- if (i)
- memset(ret->ob_digit + 2*shift + t1->ob_size, 0,
- i * sizeof(digit));
-
- /* 3. t2 <- al*bl, and copy into the low digits. */
- if ((t2 = k_mul(al, bl)) == NULL) {
- Py_DECREF(t1);
- goto fail;
- }
- assert(t2->ob_size >= 0);
- assert(t2->ob_size <= 2*shift); /* no overlap with high digits */
- memcpy(ret->ob_digit, t2->ob_digit, t2->ob_size * sizeof(digit));
-
- /* Zero out remaining digits. */
- i = 2*shift - t2->ob_size; /* number of uninitialized digits */
- if (i)
- memset(ret->ob_digit + t2->ob_size, 0, i * sizeof(digit));
-
- /* 4 & 5. Subtract ah*bh (t1) and al*bl (t2). We do al*bl first
- * because it's fresher in cache.
- */
- i = ret->ob_size - shift; /* # digits after shift */
- (void)v_isub(ret->ob_digit + shift, i, t2->ob_digit, t2->ob_size);
- Py_DECREF(t2);
-
- (void)v_isub(ret->ob_digit + shift, i, t1->ob_digit, t1->ob_size);
- Py_DECREF(t1);
-
- /* 6. t3 <- (ah+al)(bh+bl), and add into result. */
- if ((t1 = x_add(ah, al)) == NULL) goto fail;
- Py_DECREF(ah);
- Py_DECREF(al);
- ah = al = NULL;
-
- if (a == b) {
- t2 = t1;
- Py_INCREF(t2);
- }
- else if ((t2 = x_add(bh, bl)) == NULL) {
- Py_DECREF(t1);
- goto fail;
- }
- Py_DECREF(bh);
- Py_DECREF(bl);
- bh = bl = NULL;
-
- t3 = k_mul(t1, t2);
- Py_DECREF(t1);
- Py_DECREF(t2);
- if (t3 == NULL) goto fail;
- assert(t3->ob_size >= 0);
-
- /* Add t3. It's not obvious why we can't run out of room here.
- * See the (*) comment after this function.
- */
- (void)v_iadd(ret->ob_digit + shift, i, t3->ob_digit, t3->ob_size);
- Py_DECREF(t3);
-
- return long_normalize(ret);
-
- fail:
- Py_XDECREF(ret);
- Py_XDECREF(ah);
- Py_XDECREF(al);
- Py_XDECREF(bh);
- Py_XDECREF(bl);
- return NULL;
-}
-
-/* (*) Why adding t3 can't "run out of room" above.
-
-Let f(x) mean the floor of x and c(x) mean the ceiling of x. Some facts
-to start with:
-
-1. For any integer i, i = c(i/2) + f(i/2). In particular,
- bsize = c(bsize/2) + f(bsize/2).
-2. shift = f(bsize/2)
-3. asize <= bsize
-4. Since we call k_lopsided_mul if asize*2 <= bsize, asize*2 > bsize in this
- routine, so asize > bsize/2 >= f(bsize/2) in this routine.
-
-We allocated asize + bsize result digits, and add t3 into them at an offset
-of shift. This leaves asize+bsize-shift allocated digit positions for t3
-to fit into, = (by #1 and #2) asize + f(bsize/2) + c(bsize/2) - f(bsize/2) =
-asize + c(bsize/2) available digit positions.
-
-bh has c(bsize/2) digits, and bl at most f(size/2) digits. So bh+hl has
-at most c(bsize/2) digits + 1 bit.
-
-If asize == bsize, ah has c(bsize/2) digits, else ah has at most f(bsize/2)
-digits, and al has at most f(bsize/2) digits in any case. So ah+al has at
-most (asize == bsize ? c(bsize/2) : f(bsize/2)) digits + 1 bit.
-
-The product (ah+al)*(bh+bl) therefore has at most
-
- c(bsize/2) + (asize == bsize ? c(bsize/2) : f(bsize/2)) digits + 2 bits
-
-and we have asize + c(bsize/2) available digit positions. We need to show
-this is always enough. An instance of c(bsize/2) cancels out in both, so
-the question reduces to whether asize digits is enough to hold
-(asize == bsize ? c(bsize/2) : f(bsize/2)) digits + 2 bits. If asize < bsize,
-then we're asking whether asize digits >= f(bsize/2) digits + 2 bits. By #4,
-asize is at least f(bsize/2)+1 digits, so this in turn reduces to whether 1
-digit is enough to hold 2 bits. This is so since SHIFT=15 >= 2. If
-asize == bsize, then we're asking whether bsize digits is enough to hold
-c(bsize/2) digits + 2 bits, or equivalently (by #1) whether f(bsize/2) digits
-is enough to hold 2 bits. This is so if bsize >= 2, which holds because
-bsize >= KARATSUBA_CUTOFF >= 2.
-
-Note that since there's always enough room for (ah+al)*(bh+bl), and that's
-clearly >= each of ah*bh and al*bl, there's always enough room to subtract
-ah*bh and al*bl too.
-*/
-
-/* b has at least twice the digits of a, and a is big enough that Karatsuba
- * would pay off *if* the inputs had balanced sizes. View b as a sequence
- * of slices, each with a->ob_size digits, and multiply the slices by a,
- * one at a time. This gives k_mul balanced inputs to work with, and is
- * also cache-friendly (we compute one double-width slice of the result
- * at a time, then move on, never bactracking except for the helpful
- * single-width slice overlap between successive partial sums).
- */
-static PyLongObject *
-k_lopsided_mul(PyLongObject *a, PyLongObject *b)
-{
- const Py_ssize_t asize = ABS(a->ob_size);
- Py_ssize_t bsize = ABS(b->ob_size);
- Py_ssize_t nbdone; /* # of b digits already multiplied */
- PyLongObject *ret;
- PyLongObject *bslice = NULL;
-
- assert(asize > KARATSUBA_CUTOFF);
- assert(2 * asize <= bsize);
-
- /* Allocate result space, and zero it out. */
- ret = _PyLong_New(asize + bsize);
- if (ret == NULL)
- return NULL;
- memset(ret->ob_digit, 0, ret->ob_size * sizeof(digit));
-
- /* Successive slices of b are copied into bslice. */
- bslice = _PyLong_New(asize);
- if (bslice == NULL)
- goto fail;
-
- nbdone = 0;
- while (bsize > 0) {
- PyLongObject *product;
- const Py_ssize_t nbtouse = MIN(bsize, asize);
-
- /* Multiply the next slice of b by a. */
- memcpy(bslice->ob_digit, b->ob_digit + nbdone,
- nbtouse * sizeof(digit));
- bslice->ob_size = nbtouse;
- product = k_mul(a, bslice);
- if (product == NULL)
- goto fail;
-
- /* Add into result. */
- (void)v_iadd(ret->ob_digit + nbdone, ret->ob_size - nbdone,
- product->ob_digit, product->ob_size);
- Py_DECREF(product);
-
- bsize -= nbtouse;
- nbdone += nbtouse;
- }
-
- Py_DECREF(bslice);
- return long_normalize(ret);
-
- fail:
- Py_DECREF(ret);
- Py_XDECREF(bslice);
- return NULL;
-}
-
-static PyObject *
-long_mul(PyLongObject *v, PyLongObject *w)
-{
- PyLongObject *a, *b, *z;
-
- if (!convert_binop((PyObject *)v, (PyObject *)w, &a, &b)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- z = k_mul(a, b);
- /* Negate if exactly one of the inputs is negative. */
- if (((a->ob_size ^ b->ob_size) < 0) && z)
- z->ob_size = -(z->ob_size);
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *)z;
-}
-
-/* The / and % operators are now defined in terms of divmod().
- The expression a mod b has the value a - b*floor(a/b).
- The long_divrem function gives the remainder after division of
- |a| by |b|, with the sign of a. This is also expressed
- as a - b*trunc(a/b), if trunc truncates towards zero.
- Some examples:
- a b a rem b a mod b
- 13 10 3 3
- -13 10 -3 7
- 13 -10 3 -7
- -13 -10 -3 -3
- So, to get from rem to mod, we have to add b if a and b
- have different signs. We then subtract one from the 'div'
- part of the outcome to keep the invariant intact. */
-
-/* Compute
- * *pdiv, *pmod = divmod(v, w)
- * NULL can be passed for pdiv or pmod, in which case that part of
- * the result is simply thrown away. The caller owns a reference to
- * each of these it requests (does not pass NULL for).
- */
-static int
-l_divmod(PyLongObject *v, PyLongObject *w,
- PyLongObject **pdiv, PyLongObject **pmod)
-{
- PyLongObject *div, *mod;
-
- if (long_divrem(v, w, &div, &mod) < 0)
- return -1;
- if ((mod->ob_size < 0 && w->ob_size > 0) ||
- (mod->ob_size > 0 && w->ob_size < 0)) {
- PyLongObject *temp;
- PyLongObject *one;
- temp = (PyLongObject *) long_add(mod, w);
- Py_DECREF(mod);
- mod = temp;
- if (mod == NULL) {
- Py_DECREF(div);
- return -1;
- }
- one = (PyLongObject *) PyLong_FromLong(1L);
- if (one == NULL ||
- (temp = (PyLongObject *) long_sub(div, one)) == NULL) {
- Py_DECREF(mod);
- Py_DECREF(div);
- Py_XDECREF(one);
- return -1;
- }
- Py_DECREF(one);
- Py_DECREF(div);
- div = temp;
- }
- if (pdiv != NULL)
- *pdiv = div;
- else
- Py_DECREF(div);
-
- if (pmod != NULL)
- *pmod = mod;
- else
- Py_DECREF(mod);
-
- return 0;
-}
-
-static PyObject *
-long_div(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b, *div;
-
- CONVERT_BINOP(v, w, &a, &b);
- if (l_divmod(a, b, &div, NULL) < 0)
- div = NULL;
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *)div;
-}
-
-static PyObject *
-long_classic_div(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b, *div;
-
- CONVERT_BINOP(v, w, &a, &b);
- if (Py_DivisionWarningFlag &&
- PyErr_Warn(PyExc_DeprecationWarning, "classic long division") < 0)
- div = NULL;
- else if (l_divmod(a, b, &div, NULL) < 0)
- div = NULL;
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *)div;
-}
-
-static PyObject *
-long_true_divide(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b;
- double ad, bd;
- int failed, aexp = -1, bexp = -1;
-
- CONVERT_BINOP(v, w, &a, &b);
- ad = _PyLong_AsScaledDouble((PyObject *)a, &aexp);
- bd = _PyLong_AsScaledDouble((PyObject *)b, &bexp);
- failed = (ad == -1.0 || bd == -1.0) && PyErr_Occurred();
- Py_DECREF(a);
- Py_DECREF(b);
- if (failed)
- return NULL;
- /* 'aexp' and 'bexp' were initialized to -1 to silence gcc-4.0.x,
- but should really be set correctly after sucessful calls to
- _PyLong_AsScaledDouble() */
- assert(aexp >= 0 && bexp >= 0);
-
- if (bd == 0.0) {
- PyErr_SetString(PyExc_ZeroDivisionError,
- "long division or modulo by zero");
- return NULL;
- }
-
- /* True value is very close to ad/bd * 2**(SHIFT*(aexp-bexp)) */
- ad /= bd; /* overflow/underflow impossible here */
- aexp -= bexp;
- if (aexp > INT_MAX / SHIFT)
- goto overflow;
- else if (aexp < -(INT_MAX / SHIFT))
- return PyFloat_FromDouble(0.0); /* underflow to 0 */
- errno = 0;
- ad = ldexp(ad, aexp * SHIFT);
- if (Py_OVERFLOWED(ad)) /* ignore underflow to 0.0 */
- goto overflow;
- return PyFloat_FromDouble(ad);
-
-overflow:
- PyErr_SetString(PyExc_OverflowError,
- "long/long too large for a float");
- return NULL;
-
-}
-
-static PyObject *
-long_mod(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b, *mod;
-
- CONVERT_BINOP(v, w, &a, &b);
-
- if (l_divmod(a, b, NULL, &mod) < 0)
- mod = NULL;
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *)mod;
-}
-
-static PyObject *
-long_divmod(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b, *div, *mod;
- PyObject *z;
-
- CONVERT_BINOP(v, w, &a, &b);
-
- if (l_divmod(a, b, &div, &mod) < 0) {
- Py_DECREF(a);
- Py_DECREF(b);
- return NULL;
- }
- z = PyTuple_New(2);
- if (z != NULL) {
- PyTuple_SetItem(z, 0, (PyObject *) div);
- PyTuple_SetItem(z, 1, (PyObject *) mod);
- }
- else {
- Py_DECREF(div);
- Py_DECREF(mod);
- }
- Py_DECREF(a);
- Py_DECREF(b);
- return z;
-}
-
-/* pow(v, w, x) */
-static PyObject *
-long_pow(PyObject *v, PyObject *w, PyObject *x)
-{
- PyLongObject *a, *b, *c; /* a,b,c = v,w,x */
- int negativeOutput = 0; /* if x<0 return negative output */
-
- PyLongObject *z = NULL; /* accumulated result */
- Py_ssize_t i, j, k; /* counters */
- PyLongObject *temp = NULL;
-
- /* 5-ary values. If the exponent is large enough, table is
- * precomputed so that table[i] == a**i % c for i in range(32).
- */
- PyLongObject *table[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
- /* a, b, c = v, w, x */
- CONVERT_BINOP(v, w, &a, &b);
- if (PyLong_Check(x)) {
- c = (PyLongObject *)x;
- Py_INCREF(x);
- }
- else if (PyInt_Check(x)) {
- c = (PyLongObject *)PyLong_FromLong(PyInt_AS_LONG(x));
- if (c == NULL)
- goto Error;
- }
- else if (x == Py_None)
- c = NULL;
- else {
- Py_DECREF(a);
- Py_DECREF(b);
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- if (b->ob_size < 0) { /* if exponent is negative */
- if (c) {
- PyErr_SetString(PyExc_TypeError, "pow() 2nd argument "
- "cannot be negative when 3rd argument specified");
- goto Error;
- }
- else {
- /* else return a float. This works because we know
- that this calls float_pow() which converts its
- arguments to double. */
- Py_DECREF(a);
- Py_DECREF(b);
- return PyFloat_Type.tp_as_number->nb_power(v, w, x);
- }
- }
-
- if (c) {
- /* if modulus == 0:
- raise ValueError() */
- if (c->ob_size == 0) {
- PyErr_SetString(PyExc_ValueError,
- "pow() 3rd argument cannot be 0");
- goto Error;
- }
-
- /* if modulus < 0:
- negativeOutput = True
- modulus = -modulus */
- if (c->ob_size < 0) {
- negativeOutput = 1;
- temp = (PyLongObject *)_PyLong_Copy(c);
- if (temp == NULL)
- goto Error;
- Py_DECREF(c);
- c = temp;
- temp = NULL;
- c->ob_size = - c->ob_size;
- }
-
- /* if modulus == 1:
- return 0 */
- if ((c->ob_size == 1) && (c->ob_digit[0] == 1)) {
- z = (PyLongObject *)PyLong_FromLong(0L);
- goto Done;
- }
-
- /* if base < 0:
- base = base % modulus
- Having the base positive just makes things easier. */
- if (a->ob_size < 0) {
- if (l_divmod(a, c, NULL, &temp) < 0)
- goto Error;
- Py_DECREF(a);
- a = temp;
- temp = NULL;
- }
- }
-
- /* At this point a, b, and c are guaranteed non-negative UNLESS
- c is NULL, in which case a may be negative. */
-
- z = (PyLongObject *)PyLong_FromLong(1L);
- if (z == NULL)
- goto Error;
-
- /* Perform a modular reduction, X = X % c, but leave X alone if c
- * is NULL.
- */
-#define REDUCE(X) \
- if (c != NULL) { \
- if (l_divmod(X, c, NULL, &temp) < 0) \
- goto Error; \
- Py_XDECREF(X); \
- X = temp; \
- temp = NULL; \
- }
-
- /* Multiply two values, then reduce the result:
- result = X*Y % c. If c is NULL, skip the mod. */
-#define MULT(X, Y, result) \
-{ \
- temp = (PyLongObject *)long_mul(X, Y); \
- if (temp == NULL) \
- goto Error; \
- Py_XDECREF(result); \
- result = temp; \
- temp = NULL; \
- REDUCE(result) \
-}
-
- if (b->ob_size <= FIVEARY_CUTOFF) {
- /* Left-to-right binary exponentiation (HAC Algorithm 14.79) */
- /* http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf */
- for (i = b->ob_size - 1; i >= 0; --i) {
- digit bi = b->ob_digit[i];
-
- for (j = 1 << (SHIFT-1); j != 0; j >>= 1) {
- MULT(z, z, z)
- if (bi & j)
- MULT(z, a, z)
- }
- }
- }
- else {
- /* Left-to-right 5-ary exponentiation (HAC Algorithm 14.82) */
- Py_INCREF(z); /* still holds 1L */
- table[0] = z;
- for (i = 1; i < 32; ++i)
- MULT(table[i-1], a, table[i])
-
- for (i = b->ob_size - 1; i >= 0; --i) {
- const digit bi = b->ob_digit[i];
-
- for (j = SHIFT - 5; j >= 0; j -= 5) {
- const int index = (bi >> j) & 0x1f;
- for (k = 0; k < 5; ++k)
- MULT(z, z, z)
- if (index)
- MULT(z, table[index], z)
- }
- }
- }
-
- if (negativeOutput && (z->ob_size != 0)) {
- temp = (PyLongObject *)long_sub(z, c);
- if (temp == NULL)
- goto Error;
- Py_DECREF(z);
- z = temp;
- temp = NULL;
- }
- goto Done;
-
- Error:
- if (z != NULL) {
- Py_DECREF(z);
- z = NULL;
- }
- /* fall through */
- Done:
- if (b->ob_size > FIVEARY_CUTOFF) {
- for (i = 0; i < 32; ++i)
- Py_XDECREF(table[i]);
- }
- Py_DECREF(a);
- Py_DECREF(b);
- Py_XDECREF(c);
- Py_XDECREF(temp);
- return (PyObject *)z;
-}
-
-static PyObject *
-long_invert(PyLongObject *v)
-{
- /* Implement ~x as -(x+1) */
- PyLongObject *x;
- PyLongObject *w;
- w = (PyLongObject *)PyLong_FromLong(1L);
- if (w == NULL)
- return NULL;
- x = (PyLongObject *) long_add(v, w);
- Py_DECREF(w);
- if (x == NULL)
- return NULL;
- x->ob_size = -(x->ob_size);
- return (PyObject *)x;
-}
-
-static PyObject *
-long_pos(PyLongObject *v)
-{
- if (PyLong_CheckExact(v)) {
- Py_INCREF(v);
- return (PyObject *)v;
- }
- else
- return _PyLong_Copy(v);
-}
-
-static PyObject *
-long_neg(PyLongObject *v)
-{
- PyLongObject *z;
- if (v->ob_size == 0 && PyLong_CheckExact(v)) {
- /* -0 == 0 */
- Py_INCREF(v);
- return (PyObject *) v;
- }
- z = (PyLongObject *)_PyLong_Copy(v);
- if (z != NULL)
- z->ob_size = -(v->ob_size);
- return (PyObject *)z;
-}
-
-static PyObject *
-long_abs(PyLongObject *v)
-{
- if (v->ob_size < 0)
- return long_neg(v);
- else
- return long_pos(v);
-}
-
-static int
-long_nonzero(PyLongObject *v)
-{
- return ABS(v->ob_size) != 0;
-}
-
-static PyObject *
-long_rshift(PyLongObject *v, PyLongObject *w)
-{
- PyLongObject *a, *b;
- PyLongObject *z = NULL;
- long shiftby;
- Py_ssize_t newsize, wordshift, loshift, hishift, i, j;
- digit lomask, himask;
-
- CONVERT_BINOP((PyObject *)v, (PyObject *)w, &a, &b);
-
- if (a->ob_size < 0) {
- /* Right shifting negative numbers is harder */
- PyLongObject *a1, *a2;
- a1 = (PyLongObject *) long_invert(a);
- if (a1 == NULL)
- goto rshift_error;
- a2 = (PyLongObject *) long_rshift(a1, b);
- Py_DECREF(a1);
- if (a2 == NULL)
- goto rshift_error;
- z = (PyLongObject *) long_invert(a2);
- Py_DECREF(a2);
- }
- else {
-
- shiftby = PyLong_AsLong((PyObject *)b);
- if (shiftby == -1L && PyErr_Occurred())
- goto rshift_error;
- if (shiftby < 0) {
- PyErr_SetString(PyExc_ValueError,
- "negative shift count");
- goto rshift_error;
- }
- wordshift = shiftby / SHIFT;
- newsize = ABS(a->ob_size) - wordshift;
- if (newsize <= 0) {
- z = _PyLong_New(0);
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *)z;
- }
- loshift = shiftby % SHIFT;
- hishift = SHIFT - loshift;
- lomask = ((digit)1 << hishift) - 1;
- himask = MASK ^ lomask;
- z = _PyLong_New(newsize);
- if (z == NULL)
- goto rshift_error;
- if (a->ob_size < 0)
- z->ob_size = -(z->ob_size);
- for (i = 0, j = wordshift; i < newsize; i++, j++) {
- z->ob_digit[i] = (a->ob_digit[j] >> loshift) & lomask;
- if (i+1 < newsize)
- z->ob_digit[i] |=
- (a->ob_digit[j+1] << hishift) & himask;
- }
- z = long_normalize(z);
- }
-rshift_error:
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *) z;
-
-}
-
-static PyObject *
-long_lshift(PyObject *v, PyObject *w)
-{
- /* This version due to Tim Peters */
- PyLongObject *a, *b;
- PyLongObject *z = NULL;
- long shiftby;
- Py_ssize_t oldsize, newsize, wordshift, remshift, i, j;
- twodigits accum;
-
- CONVERT_BINOP(v, w, &a, &b);
-
- shiftby = PyLong_AsLong((PyObject *)b);
- if (shiftby == -1L && PyErr_Occurred())
- goto lshift_error;
- if (shiftby < 0) {
- PyErr_SetString(PyExc_ValueError, "negative shift count");
- goto lshift_error;
- }
- if ((long)(int)shiftby != shiftby) {
- PyErr_SetString(PyExc_ValueError,
- "outrageous left shift count");
- goto lshift_error;
- }
- /* wordshift, remshift = divmod(shiftby, SHIFT) */
- wordshift = (int)shiftby / SHIFT;
- remshift = (int)shiftby - wordshift * SHIFT;
-
- oldsize = ABS(a->ob_size);
- newsize = oldsize + wordshift;
- if (remshift)
- ++newsize;
- z = _PyLong_New(newsize);
- if (z == NULL)
- goto lshift_error;
- if (a->ob_size < 0)
- z->ob_size = -(z->ob_size);
- for (i = 0; i < wordshift; i++)
- z->ob_digit[i] = 0;
- accum = 0;
- for (i = wordshift, j = 0; j < oldsize; i++, j++) {
- accum |= (twodigits)a->ob_digit[j] << remshift;
- z->ob_digit[i] = (digit)(accum & MASK);
- accum >>= SHIFT;
- }
- if (remshift)
- z->ob_digit[newsize-1] = (digit)accum;
- else
- assert(!accum);
- z = long_normalize(z);
-lshift_error:
- Py_DECREF(a);
- Py_DECREF(b);
- return (PyObject *) z;
-}
-
-
-/* Bitwise and/xor/or operations */
-
-static PyObject *
-long_bitwise(PyLongObject *a,
- int op, /* '&', '|', '^' */
- PyLongObject *b)
-{
- digit maska, maskb; /* 0 or MASK */
- int negz;
- Py_ssize_t size_a, size_b, size_z;
- PyLongObject *z;
- int i;
- digit diga, digb;
- PyObject *v;
-
- if (a->ob_size < 0) {
- a = (PyLongObject *) long_invert(a);
- if (a == NULL)
- return NULL;
- maska = MASK;
- }
- else {
- Py_INCREF(a);
- maska = 0;
- }
- if (b->ob_size < 0) {
- b = (PyLongObject *) long_invert(b);
- if (b == NULL) {
- Py_DECREF(a);
- return NULL;
- }
- maskb = MASK;
- }
- else {
- Py_INCREF(b);
- maskb = 0;
- }
-
- negz = 0;
- switch (op) {
- case '^':
- if (maska != maskb) {
- maska ^= MASK;
- negz = -1;
- }
- break;
- case '&':
- if (maska && maskb) {
- op = '|';
- maska ^= MASK;
- maskb ^= MASK;
- negz = -1;
- }
- break;
- case '|':
- if (maska || maskb) {
- op = '&';
- maska ^= MASK;
- maskb ^= MASK;
- negz = -1;
- }
- break;
- }
-
- /* JRH: The original logic here was to allocate the result value (z)
- as the longer of the two operands. However, there are some cases
- where the result is guaranteed to be shorter than that: AND of two
- positives, OR of two negatives: use the shorter number. AND with
- mixed signs: use the positive number. OR with mixed signs: use the
- negative number. After the transformations above, op will be '&'
- iff one of these cases applies, and mask will be non-0 for operands
- whose length should be ignored.
- */
-
- size_a = a->ob_size;
- size_b = b->ob_size;
- size_z = op == '&'
- ? (maska
- ? size_b
- : (maskb ? size_a : MIN(size_a, size_b)))
- : MAX(size_a, size_b);
- z = _PyLong_New(size_z);
- if (z == NULL) {
- Py_DECREF(a);
- Py_DECREF(b);
- return NULL;
- }
-
- for (i = 0; i < size_z; ++i) {
- diga = (i < size_a ? a->ob_digit[i] : 0) ^ maska;
- digb = (i < size_b ? b->ob_digit[i] : 0) ^ maskb;
- switch (op) {
- case '&': z->ob_digit[i] = diga & digb; break;
- case '|': z->ob_digit[i] = diga | digb; break;
- case '^': z->ob_digit[i] = diga ^ digb; break;
- }
- }
-
- Py_DECREF(a);
- Py_DECREF(b);
- z = long_normalize(z);
- if (negz == 0)
- return (PyObject *) z;
- v = long_invert(z);
- Py_DECREF(z);
- return v;
-}
-
-static PyObject *
-long_and(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b;
- PyObject *c;
- CONVERT_BINOP(v, w, &a, &b);
- c = long_bitwise(a, '&', b);
- Py_DECREF(a);
- Py_DECREF(b);
- return c;
-}
-
-static PyObject *
-long_xor(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b;
- PyObject *c;
- CONVERT_BINOP(v, w, &a, &b);
- c = long_bitwise(a, '^', b);
- Py_DECREF(a);
- Py_DECREF(b);
- return c;
-}
-
-static PyObject *
-long_or(PyObject *v, PyObject *w)
-{
- PyLongObject *a, *b;
- PyObject *c;
- CONVERT_BINOP(v, w, &a, &b);
- c = long_bitwise(a, '|', b);
- Py_DECREF(a);
- Py_DECREF(b);
- return c;
-}
-
-static int
-long_coerce(PyObject **pv, PyObject **pw)
-{
- if (PyInt_Check(*pw)) {
- *pw = PyLong_FromLong(PyInt_AS_LONG(*pw));
- Py_INCREF(*pv);
- return 0;
- }
- else if (PyLong_Check(*pw)) {
- Py_INCREF(*pv);
- Py_INCREF(*pw);
- return 0;
- }
- return 1; /* Can't do it */
-}
-
-static PyObject *
-long_long(PyObject *v)
-{
- if (PyLong_CheckExact(v))
- Py_INCREF(v);
- else
- v = _PyLong_Copy((PyLongObject *)v);
- return v;
-}
-
-static PyObject *
-long_int(PyObject *v)
-{
- long x;
- x = PyLong_AsLong(v);
- if (PyErr_Occurred()) {
- if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
- PyErr_Clear();
- if (PyLong_CheckExact(v)) {
- Py_INCREF(v);
- return v;
- }
- else
- return _PyLong_Copy((PyLongObject *)v);
- }
- else
- return NULL;
- }
- return PyInt_FromLong(x);
-}
-
-static PyObject *
-long_float(PyObject *v)
-{
- double result;
- result = PyLong_AsDouble(v);
- if (result == -1.0 && PyErr_Occurred())
- return NULL;
- return PyFloat_FromDouble(result);
-}
-
-static PyObject *
-long_oct(PyObject *v)
-{
- return long_format(v, 8, 1);
-}
-
-static PyObject *
-long_hex(PyObject *v)
-{
- return long_format(v, 16, 1);
-}
-
-static PyObject *
-long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyObject *
-long_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *x = NULL;
- int base = -909; /* unlikely! */
- static char *kwlist[] = {"x", "base", 0};
-
- if (type != &PyLong_Type)
- return long_subtype_new(type, args, kwds); /* Wimp out */
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:long", kwlist,
- &x, &base))
- return NULL;
- if (x == NULL)
- return PyLong_FromLong(0L);
- if (base == -909)
- return PyNumber_Long(x);
- else if (PyString_Check(x)) {
- /* Since PyLong_FromString doesn't have a length parameter,
- * check here for possible NULs in the string. */
- char *string = PyString_AS_STRING(x);
- if (strlen(string) != PyString_Size(x)) {
- /* create a repr() of the input string,
- * just like PyLong_FromString does. */
- PyObject *srepr;
- srepr = PyObject_Repr(x);
- if (srepr == NULL)
- return NULL;
- PyErr_Format(PyExc_ValueError,
- "invalid literal for long() with base %d: %s",
- base, PyString_AS_STRING(srepr));
- Py_DECREF(srepr);
- return NULL;
- }
- return PyLong_FromString(PyString_AS_STRING(x), NULL, base);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(x))
- return PyLong_FromUnicode(PyUnicode_AS_UNICODE(x),
- PyUnicode_GET_SIZE(x),
- base);
-#endif
- else {
- PyErr_SetString(PyExc_TypeError,
- "long() can't convert non-string with explicit base");
- return NULL;
- }
-}
-
-/* Wimpy, slow approach to tp_new calls for subtypes of long:
- first create a regular long from whatever arguments we got,
- then allocate a subtype instance and initialize it from
- the regular long. The regular long is then thrown away.
-*/
-static PyObject *
-long_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyLongObject *tmp, *newobj;
- Py_ssize_t i, n;
-
- assert(PyType_IsSubtype(type, &PyLong_Type));
- tmp = (PyLongObject *)long_new(&PyLong_Type, args, kwds);
- if (tmp == NULL)
- return NULL;
- assert(PyLong_CheckExact(tmp));
- n = tmp->ob_size;
- if (n < 0)
- n = -n;
- newobj = (PyLongObject *)type->tp_alloc(type, n);
- if (newobj == NULL) {
- Py_DECREF(tmp);
- return NULL;
- }
- assert(PyLong_Check(newobj));
- newobj->ob_size = tmp->ob_size;
- for (i = 0; i < n; i++)
- newobj->ob_digit[i] = tmp->ob_digit[i];
- Py_DECREF(tmp);
- return (PyObject *)newobj;
-}
-
-static PyObject *
-long_getnewargs(PyLongObject *v)
-{
- return Py_BuildValue("(N)", _PyLong_Copy(v));
-}
-
-static PyMethodDef long_methods[] = {
- {"__getnewargs__", (PyCFunction)long_getnewargs, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-PyDoc_STRVAR(long_doc,
-"long(x[, base]) -> integer\n\
-\n\
-Convert a string or number to a long integer, if possible. A floating\n\
-point argument will be truncated towards zero (this does not include a\n\
-string representation of a floating point number!) When converting a\n\
-string, use the optional base. It is an error to supply a base when\n\
-converting a non-string.");
-
-static PyNumberMethods long_as_number = {
- (binaryfunc) long_add, /*nb_add*/
- (binaryfunc) long_sub, /*nb_subtract*/
- (binaryfunc) long_mul, /*nb_multiply*/
- long_classic_div, /*nb_divide*/
- long_mod, /*nb_remainder*/
- long_divmod, /*nb_divmod*/
- long_pow, /*nb_power*/
- (unaryfunc) long_neg, /*nb_negative*/
- (unaryfunc) long_pos, /*tp_positive*/
- (unaryfunc) long_abs, /*tp_absolute*/
- (inquiry) long_nonzero, /*tp_nonzero*/
- (unaryfunc) long_invert, /*nb_invert*/
- long_lshift, /*nb_lshift*/
- (binaryfunc) long_rshift, /*nb_rshift*/
- long_and, /*nb_and*/
- long_xor, /*nb_xor*/
- long_or, /*nb_or*/
- long_coerce, /*nb_coerce*/
- long_int, /*nb_int*/
- long_long, /*nb_long*/
- long_float, /*nb_float*/
- long_oct, /*nb_oct*/
- long_hex, /*nb_hex*/
- 0, /* nb_inplace_add */
- 0, /* nb_inplace_subtract */
- 0, /* nb_inplace_multiply */
- 0, /* nb_inplace_divide */
- 0, /* nb_inplace_remainder */
- 0, /* nb_inplace_power */
- 0, /* nb_inplace_lshift */
- 0, /* nb_inplace_rshift */
- 0, /* nb_inplace_and */
- 0, /* nb_inplace_xor */
- 0, /* nb_inplace_or */
- long_div, /* nb_floor_divide */
- long_true_divide, /* nb_true_divide */
- 0, /* nb_inplace_floor_divide */
- 0, /* nb_inplace_true_divide */
- long_long, /* nb_index */
-};
-
-PyTypeObject PyLong_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "long", /* tp_name */
- sizeof(PyLongObject) - sizeof(digit), /* tp_basicsize */
- sizeof(digit), /* tp_itemsize */
- long_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)long_compare, /* tp_compare */
- long_repr, /* tp_repr */
- &long_as_number, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)long_hash, /* tp_hash */
- 0, /* tp_call */
- long_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- long_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- long_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- long_new, /* tp_new */
- PyObject_Del, /* tp_free */
-};
diff --git a/sys/src/cmd/python/Objects/methodobject.c b/sys/src/cmd/python/Objects/methodobject.c
deleted file mode 100644
index ecc9a0ab5..000000000
--- a/sys/src/cmd/python/Objects/methodobject.c
+++ /dev/null
@@ -1,365 +0,0 @@
-
-/* Method object implementation */
-
-#include "Python.h"
-#include "structmember.h"
-
-static PyCFunctionObject *free_list = NULL;
-
-PyObject *
-PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
-{
- PyCFunctionObject *op;
- op = free_list;
- if (op != NULL) {
- free_list = (PyCFunctionObject *)(op->m_self);
- PyObject_INIT(op, &PyCFunction_Type);
- }
- else {
- op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
- if (op == NULL)
- return NULL;
- }
- op->m_ml = ml;
- Py_XINCREF(self);
- op->m_self = self;
- Py_XINCREF(module);
- op->m_module = module;
- _PyObject_GC_TRACK(op);
- return (PyObject *)op;
-}
-
-PyCFunction
-PyCFunction_GetFunction(PyObject *op)
-{
- if (!PyCFunction_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyCFunctionObject *)op) -> m_ml -> ml_meth;
-}
-
-PyObject *
-PyCFunction_GetSelf(PyObject *op)
-{
- if (!PyCFunction_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return ((PyCFunctionObject *)op) -> m_self;
-}
-
-int
-PyCFunction_GetFlags(PyObject *op)
-{
- if (!PyCFunction_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return ((PyCFunctionObject *)op) -> m_ml -> ml_flags;
-}
-
-PyObject *
-PyCFunction_Call(PyObject *func, PyObject *arg, PyObject *kw)
-{
- PyCFunctionObject* f = (PyCFunctionObject*)func;
- PyCFunction meth = PyCFunction_GET_FUNCTION(func);
- PyObject *self = PyCFunction_GET_SELF(func);
- Py_ssize_t size;
-
- switch (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) {
- case METH_VARARGS:
- if (kw == NULL || PyDict_Size(kw) == 0)
- return (*meth)(self, arg);
- break;
- case METH_VARARGS | METH_KEYWORDS:
- case METH_OLDARGS | METH_KEYWORDS:
- return (*(PyCFunctionWithKeywords)meth)(self, arg, kw);
- case METH_NOARGS:
- if (kw == NULL || PyDict_Size(kw) == 0) {
- size = PyTuple_GET_SIZE(arg);
- if (size == 0)
- return (*meth)(self, NULL);
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes no arguments (%zd given)",
- f->m_ml->ml_name, size);
- return NULL;
- }
- break;
- case METH_O:
- if (kw == NULL || PyDict_Size(kw) == 0) {
- size = PyTuple_GET_SIZE(arg);
- if (size == 1)
- return (*meth)(self, PyTuple_GET_ITEM(arg, 0));
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes exactly one argument (%zd given)",
- f->m_ml->ml_name, size);
- return NULL;
- }
- break;
- case METH_OLDARGS:
- /* the really old style */
- if (kw == NULL || PyDict_Size(kw) == 0) {
- size = PyTuple_GET_SIZE(arg);
- if (size == 1)
- arg = PyTuple_GET_ITEM(arg, 0);
- else if (size == 0)
- arg = NULL;
- return (*meth)(self, arg);
- }
- break;
- default:
- PyErr_BadInternalCall();
- return NULL;
- }
- PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
- f->m_ml->ml_name);
- return NULL;
-}
-
-/* Methods (the standard built-in methods, that is) */
-
-static void
-meth_dealloc(PyCFunctionObject *m)
-{
- _PyObject_GC_UNTRACK(m);
- Py_XDECREF(m->m_self);
- Py_XDECREF(m->m_module);
- m->m_self = (PyObject *)free_list;
- free_list = m;
-}
-
-static PyObject *
-meth_get__doc__(PyCFunctionObject *m, void *closure)
-{
- const char *doc = m->m_ml->ml_doc;
-
- if (doc != NULL)
- return PyString_FromString(doc);
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-meth_get__name__(PyCFunctionObject *m, void *closure)
-{
- return PyString_FromString(m->m_ml->ml_name);
-}
-
-static int
-meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
-{
- Py_VISIT(m->m_self);
- Py_VISIT(m->m_module);
- return 0;
-}
-
-static PyObject *
-meth_get__self__(PyCFunctionObject *m, void *closure)
-{
- PyObject *self;
- if (PyEval_GetRestricted()) {
- PyErr_SetString(PyExc_RuntimeError,
- "method.__self__ not accessible in restricted mode");
- return NULL;
- }
- self = m->m_self;
- if (self == NULL)
- self = Py_None;
- Py_INCREF(self);
- return self;
-}
-
-static PyGetSetDef meth_getsets [] = {
- {"__doc__", (getter)meth_get__doc__, NULL, NULL},
- {"__name__", (getter)meth_get__name__, NULL, NULL},
- {"__self__", (getter)meth_get__self__, NULL, NULL},
- {0}
-};
-
-#define OFF(x) offsetof(PyCFunctionObject, x)
-
-static PyMemberDef meth_members[] = {
- {"__module__", T_OBJECT, OFF(m_module), WRITE_RESTRICTED},
- {NULL}
-};
-
-static PyObject *
-meth_repr(PyCFunctionObject *m)
-{
- if (m->m_self == NULL)
- return PyString_FromFormat("<built-in function %s>",
- m->m_ml->ml_name);
- return PyString_FromFormat("<built-in method %s of %s object at %p>",
- m->m_ml->ml_name,
- m->m_self->ob_type->tp_name,
- m->m_self);
-}
-
-static int
-meth_compare(PyCFunctionObject *a, PyCFunctionObject *b)
-{
- if (a->m_self != b->m_self)
- return (a->m_self < b->m_self) ? -1 : 1;
- if (a->m_ml->ml_meth == b->m_ml->ml_meth)
- return 0;
- if (strcmp(a->m_ml->ml_name, b->m_ml->ml_name) < 0)
- return -1;
- else
- return 1;
-}
-
-static long
-meth_hash(PyCFunctionObject *a)
-{
- long x,y;
- if (a->m_self == NULL)
- x = 0;
- else {
- x = PyObject_Hash(a->m_self);
- if (x == -1)
- return -1;
- }
- y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
- if (y == -1)
- return -1;
- x ^= y;
- if (x == -1)
- x = -2;
- return x;
-}
-
-
-PyTypeObject PyCFunction_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "builtin_function_or_method",
- sizeof(PyCFunctionObject),
- 0,
- (destructor)meth_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)meth_compare, /* tp_compare */
- (reprfunc)meth_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)meth_hash, /* tp_hash */
- PyCFunction_Call, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)meth_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- meth_members, /* tp_members */
- meth_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
-};
-
-/* List all methods in a chain -- helper for findmethodinchain */
-
-static PyObject *
-listmethodchain(PyMethodChain *chain)
-{
- PyMethodChain *c;
- PyMethodDef *ml;
- int i, n;
- PyObject *v;
-
- n = 0;
- for (c = chain; c != NULL; c = c->link) {
- for (ml = c->methods; ml->ml_name != NULL; ml++)
- n++;
- }
- v = PyList_New(n);
- if (v == NULL)
- return NULL;
- i = 0;
- for (c = chain; c != NULL; c = c->link) {
- for (ml = c->methods; ml->ml_name != NULL; ml++) {
- PyList_SetItem(v, i, PyString_FromString(ml->ml_name));
- i++;
- }
- }
- if (PyErr_Occurred()) {
- Py_DECREF(v);
- return NULL;
- }
- PyList_Sort(v);
- return v;
-}
-
-/* Find a method in a method chain */
-
-PyObject *
-Py_FindMethodInChain(PyMethodChain *chain, PyObject *self, const char *name)
-{
- if (name[0] == '_' && name[1] == '_') {
- if (strcmp(name, "__methods__") == 0)
- return listmethodchain(chain);
- if (strcmp(name, "__doc__") == 0) {
- const char *doc = self->ob_type->tp_doc;
- if (doc != NULL)
- return PyString_FromString(doc);
- }
- }
- while (chain != NULL) {
- PyMethodDef *ml = chain->methods;
- for (; ml->ml_name != NULL; ml++) {
- if (name[0] == ml->ml_name[0] &&
- strcmp(name+1, ml->ml_name+1) == 0)
- /* XXX */
- return PyCFunction_New(ml, self);
- }
- chain = chain->link;
- }
- PyErr_SetString(PyExc_AttributeError, name);
- return NULL;
-}
-
-/* Find a method in a single method list */
-
-PyObject *
-Py_FindMethod(PyMethodDef *methods, PyObject *self, const char *name)
-{
- PyMethodChain chain;
- chain.methods = methods;
- chain.link = NULL;
- return Py_FindMethodInChain(&chain, self, name);
-}
-
-/* Clear out the free list */
-
-void
-PyCFunction_Fini(void)
-{
- while (free_list) {
- PyCFunctionObject *v = free_list;
- free_list = (PyCFunctionObject *)(v->m_self);
- PyObject_GC_Del(v);
- }
-}
-
-/* PyCFunction_New() is now just a macro that calls PyCFunction_NewEx(),
- but it's part of the API so we need to keep a function around that
- existing C extensions can call.
-*/
-
-#undef PyCFunction_New
-PyAPI_FUNC(PyObject *) PyCFunction_New(PyMethodDef *, PyObject *);
-
-PyObject *
-PyCFunction_New(PyMethodDef *ml, PyObject *self)
-{
- return PyCFunction_NewEx(ml, self, NULL);
-}
diff --git a/sys/src/cmd/python/Objects/mkfile b/sys/src/cmd/python/Objects/mkfile
deleted file mode 100644
index 9771b2639..000000000
--- a/sys/src/cmd/python/Objects/mkfile
+++ /dev/null
@@ -1,46 +0,0 @@
-APE=/sys/src/ape
-<$APE/config
-
-LIB=../libpython.a$O
-
-OFILES=\
- abstract.$O\
- boolobject.$O\
- bufferobject.$O\
- cellobject.$O\
- classobject.$O\
- cobject.$O\
- codeobject.$O\
- complexobject.$O\
- descrobject.$O\
- dictobject.$O\
- enumobject.$O\
- exceptions.$O\
- fileobject.$O\
- floatobject.$O\
- frameobject.$O\
- funcobject.$O\
- genobject.$O\
- intobject.$O\
- iterobject.$O\
- listobject.$O\
- longobject.$O\
- methodobject.$O\
- moduleobject.$O\
- object.$O\
- obmalloc.$O\
- rangeobject.$O\
- setobject.$O\
- sliceobject.$O\
- stringobject.$O\
- structseq.$O\
- tupleobject.$O\
- typeobject.$O\
- unicodectype.$O\
- unicodeobject.$O\
- weakrefobject.$O\
-
-</sys/src/cmd/mklib
-
-CFLAGS=-c -I.. -I../Include -DT$objtype -DPy_BUILD_CORE -DNDEBUG
-
diff --git a/sys/src/cmd/python/Objects/moduleobject.c b/sys/src/cmd/python/Objects/moduleobject.c
deleted file mode 100644
index e454fcf32..000000000
--- a/sys/src/cmd/python/Objects/moduleobject.c
+++ /dev/null
@@ -1,259 +0,0 @@
-
-/* Module object implementation */
-
-#include "Python.h"
-#include "structmember.h"
-
-typedef struct {
- PyObject_HEAD
- PyObject *md_dict;
-} PyModuleObject;
-
-static PyMemberDef module_members[] = {
- {"__dict__", T_OBJECT, offsetof(PyModuleObject, md_dict), READONLY},
- {0}
-};
-
-PyObject *
-PyModule_New(const char *name)
-{
- PyModuleObject *m;
- PyObject *nameobj;
- m = PyObject_GC_New(PyModuleObject, &PyModule_Type);
- if (m == NULL)
- return NULL;
- nameobj = PyString_FromString(name);
- m->md_dict = PyDict_New();
- if (m->md_dict == NULL || nameobj == NULL)
- goto fail;
- if (PyDict_SetItemString(m->md_dict, "__name__", nameobj) != 0)
- goto fail;
- if (PyDict_SetItemString(m->md_dict, "__doc__", Py_None) != 0)
- goto fail;
- Py_DECREF(nameobj);
- PyObject_GC_Track(m);
- return (PyObject *)m;
-
- fail:
- Py_XDECREF(nameobj);
- Py_DECREF(m);
- return NULL;
-}
-
-PyObject *
-PyModule_GetDict(PyObject *m)
-{
- PyObject *d;
- if (!PyModule_Check(m)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- d = ((PyModuleObject *)m) -> md_dict;
- if (d == NULL)
- ((PyModuleObject *)m) -> md_dict = d = PyDict_New();
- return d;
-}
-
-char *
-PyModule_GetName(PyObject *m)
-{
- PyObject *d;
- PyObject *nameobj;
- if (!PyModule_Check(m)) {
- PyErr_BadArgument();
- return NULL;
- }
- d = ((PyModuleObject *)m)->md_dict;
- if (d == NULL ||
- (nameobj = PyDict_GetItemString(d, "__name__")) == NULL ||
- !PyString_Check(nameobj))
- {
- PyErr_SetString(PyExc_SystemError, "nameless module");
- return NULL;
- }
- return PyString_AsString(nameobj);
-}
-
-char *
-PyModule_GetFilename(PyObject *m)
-{
- PyObject *d;
- PyObject *fileobj;
- if (!PyModule_Check(m)) {
- PyErr_BadArgument();
- return NULL;
- }
- d = ((PyModuleObject *)m)->md_dict;
- if (d == NULL ||
- (fileobj = PyDict_GetItemString(d, "__file__")) == NULL ||
- !PyString_Check(fileobj))
- {
- PyErr_SetString(PyExc_SystemError, "module filename missing");
- return NULL;
- }
- return PyString_AsString(fileobj);
-}
-
-void
-_PyModule_Clear(PyObject *m)
-{
- /* To make the execution order of destructors for global
- objects a bit more predictable, we first zap all objects
- whose name starts with a single underscore, before we clear
- the entire dictionary. We zap them by replacing them with
- None, rather than deleting them from the dictionary, to
- avoid rehashing the dictionary (to some extent). */
-
- Py_ssize_t pos;
- PyObject *key, *value;
- PyObject *d;
-
- d = ((PyModuleObject *)m)->md_dict;
- if (d == NULL)
- return;
-
- /* First, clear only names starting with a single underscore */
- pos = 0;
- while (PyDict_Next(d, &pos, &key, &value)) {
- if (value != Py_None && PyString_Check(key)) {
- char *s = PyString_AsString(key);
- if (s[0] == '_' && s[1] != '_') {
- if (Py_VerboseFlag > 1)
- PySys_WriteStderr("# clear[1] %s\n", s);
- PyDict_SetItem(d, key, Py_None);
- }
- }
- }
-
- /* Next, clear all names except for __builtins__ */
- pos = 0;
- while (PyDict_Next(d, &pos, &key, &value)) {
- if (value != Py_None && PyString_Check(key)) {
- char *s = PyString_AsString(key);
- if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {
- if (Py_VerboseFlag > 1)
- PySys_WriteStderr("# clear[2] %s\n", s);
- PyDict_SetItem(d, key, Py_None);
- }
- }
- }
-
- /* Note: we leave __builtins__ in place, so that destructors
- of non-global objects defined in this module can still use
- builtins, in particularly 'None'. */
-
-}
-
-/* Methods */
-
-static int
-module_init(PyModuleObject *m, PyObject *args, PyObject *kwds)
-{
- static char *kwlist[] = {"name", "doc", NULL};
- PyObject *dict, *name = Py_None, *doc = Py_None;
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|O:module.__init__",
- kwlist, &name, &doc))
- return -1;
- dict = m->md_dict;
- if (dict == NULL) {
- dict = PyDict_New();
- if (dict == NULL)
- return -1;
- m->md_dict = dict;
- }
- if (PyDict_SetItemString(dict, "__name__", name) < 0)
- return -1;
- if (PyDict_SetItemString(dict, "__doc__", doc) < 0)
- return -1;
- return 0;
-}
-
-static void
-module_dealloc(PyModuleObject *m)
-{
- PyObject_GC_UnTrack(m);
- if (m->md_dict != NULL) {
- _PyModule_Clear((PyObject *)m);
- Py_DECREF(m->md_dict);
- }
- m->ob_type->tp_free((PyObject *)m);
-}
-
-static PyObject *
-module_repr(PyModuleObject *m)
-{
- char *name;
- char *filename;
-
- name = PyModule_GetName((PyObject *)m);
- if (name == NULL) {
- PyErr_Clear();
- name = "?";
- }
- filename = PyModule_GetFilename((PyObject *)m);
- if (filename == NULL) {
- PyErr_Clear();
- return PyString_FromFormat("<module '%s' (built-in)>", name);
- }
- return PyString_FromFormat("<module '%s' from '%s'>", name, filename);
-}
-
-/* We only need a traverse function, no clear function: If the module
- is in a cycle, md_dict will be cleared as well, which will break
- the cycle. */
-static int
-module_traverse(PyModuleObject *m, visitproc visit, void *arg)
-{
- Py_VISIT(m->md_dict);
- return 0;
-}
-
-PyDoc_STRVAR(module_doc,
-"module(name[, doc])\n\
-\n\
-Create a module object.\n\
-The name must be a string; the optional doc argument can have any type.");
-
-PyTypeObject PyModule_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "module", /* tp_name */
- sizeof(PyModuleObject), /* tp_size */
- 0, /* tp_itemsize */
- (destructor)module_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)module_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- module_doc, /* tp_doc */
- (traverseproc)module_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- module_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(PyModuleObject, md_dict), /* tp_dictoffset */
- (initproc)module_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
diff --git a/sys/src/cmd/python/Objects/object.c b/sys/src/cmd/python/Objects/object.c
deleted file mode 100644
index b0672f30e..000000000
--- a/sys/src/cmd/python/Objects/object.c
+++ /dev/null
@@ -1,2139 +0,0 @@
-
-/* Generic object operations; and implementation of None (NoObject) */
-
-#include "Python.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef Py_REF_DEBUG
-Py_ssize_t _Py_RefTotal;
-
-Py_ssize_t
-_Py_GetRefTotal(void)
-{
- PyObject *o;
- Py_ssize_t total = _Py_RefTotal;
- /* ignore the references to the dummy object of the dicts and sets
- because they are not reliable and not useful (now that the
- hash table code is well-tested) */
- o = _PyDict_Dummy();
- if (o != NULL)
- total -= o->ob_refcnt;
- o = _PySet_Dummy();
- if (o != NULL)
- total -= o->ob_refcnt;
- return total;
-}
-#endif /* Py_REF_DEBUG */
-
-int Py_DivisionWarningFlag;
-
-/* 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! */
-
-#ifdef Py_TRACE_REFS
-/* Head of circular doubly-linked list of all objects. These are linked
- * together via the _ob_prev and _ob_next members of a PyObject, which
- * exist only in a Py_TRACE_REFS build.
- */
-static PyObject refchain = {&refchain, &refchain};
-
-/* Insert op at the front of the list of all objects. If force is true,
- * op is added even if _ob_prev and _ob_next are non-NULL already. If
- * force is false amd _ob_prev or _ob_next are non-NULL, do nothing.
- * force should be true if and only if op points to freshly allocated,
- * uninitialized memory, or you've unlinked op from the list and are
- * relinking it into the front.
- * Note that objects are normally added to the list via _Py_NewReference,
- * which is called by PyObject_Init. Not all objects are initialized that
- * way, though; exceptions include statically allocated type objects, and
- * statically allocated singletons (like Py_True and Py_None).
- */
-void
-_Py_AddToAllObjects(PyObject *op, int force)
-{
-#ifdef Py_DEBUG
- if (!force) {
- /* If it's initialized memory, op must be in or out of
- * the list unambiguously.
- */
- assert((op->_ob_prev == NULL) == (op->_ob_next == NULL));
- }
-#endif
- if (force || op->_ob_prev == NULL) {
- op->_ob_next = refchain._ob_next;
- op->_ob_prev = &refchain;
- refchain._ob_next->_ob_prev = op;
- refchain._ob_next = op;
- }
-}
-#endif /* Py_TRACE_REFS */
-
-#ifdef COUNT_ALLOCS
-static PyTypeObject *type_list;
-/* All types are added to type_list, at least when
- they get one object created. That makes them
- immortal, which unfortunately contributes to
- garbage itself. If unlist_types_without_objects
- is set, they will be removed from the type_list
- once the last object is deallocated. */
-int unlist_types_without_objects;
-extern int tuple_zero_allocs, fast_tuple_allocs;
-extern int quick_int_allocs, quick_neg_int_allocs;
-extern int null_strings, one_strings;
-void
-dump_counts(FILE* f)
-{
- PyTypeObject *tp;
-
- for (tp = type_list; tp; tp = tp->tp_next)
- fprintf(f, "%s alloc'd: %d, freed: %d, max in use: %d\n",
- tp->tp_name, tp->tp_allocs, tp->tp_frees,
- tp->tp_maxalloc);
- fprintf(f, "fast tuple allocs: %d, empty: %d\n",
- fast_tuple_allocs, tuple_zero_allocs);
- fprintf(f, "fast int allocs: pos: %d, neg: %d\n",
- quick_int_allocs, quick_neg_int_allocs);
- fprintf(f, "null strings: %d, 1-strings: %d\n",
- null_strings, one_strings);
-}
-
-PyObject *
-get_counts(void)
-{
- PyTypeObject *tp;
- PyObject *result;
- PyObject *v;
-
- result = PyList_New(0);
- if (result == NULL)
- return NULL;
- for (tp = type_list; tp; tp = tp->tp_next) {
- v = Py_BuildValue("(snnn)", tp->tp_name, tp->tp_allocs,
- tp->tp_frees, tp->tp_maxalloc);
- if (v == NULL) {
- Py_DECREF(result);
- return NULL;
- }
- if (PyList_Append(result, v) < 0) {
- Py_DECREF(v);
- Py_DECREF(result);
- return NULL;
- }
- Py_DECREF(v);
- }
- return result;
-}
-
-void
-inc_count(PyTypeObject *tp)
-{
- if (tp->tp_next == NULL && tp->tp_prev == NULL) {
- /* first time; insert in linked list */
- if (tp->tp_next != NULL) /* sanity check */
- Py_FatalError("XXX inc_count sanity check");
- if (type_list)
- type_list->tp_prev = tp;
- tp->tp_next = type_list;
- /* Note that as of Python 2.2, heap-allocated type objects
- * can go away, but this code requires that they stay alive
- * until program exit. That's why we're careful with
- * refcounts here. type_list gets a new reference to tp,
- * while ownership of the reference type_list used to hold
- * (if any) was transferred to tp->tp_next in the line above.
- * tp is thus effectively immortal after this.
- */
- Py_INCREF(tp);
- type_list = tp;
-#ifdef Py_TRACE_REFS
- /* Also insert in the doubly-linked list of all objects,
- * if not already there.
- */
- _Py_AddToAllObjects((PyObject *)tp, 0);
-#endif
- }
- tp->tp_allocs++;
- if (tp->tp_allocs - tp->tp_frees > tp->tp_maxalloc)
- tp->tp_maxalloc = tp->tp_allocs - tp->tp_frees;
-}
-
-void dec_count(PyTypeObject *tp)
-{
- tp->tp_frees++;
- if (unlist_types_without_objects &&
- tp->tp_allocs == tp->tp_frees) {
- /* unlink the type from type_list */
- if (tp->tp_prev)
- tp->tp_prev->tp_next = tp->tp_next;
- else
- type_list = tp->tp_next;
- if (tp->tp_next)
- tp->tp_next->tp_prev = tp->tp_prev;
- tp->tp_next = tp->tp_prev = NULL;
- Py_DECREF(tp);
- }
-}
-
-#endif
-
-#ifdef Py_REF_DEBUG
-/* Log a fatal error; doesn't return. */
-void
-_Py_NegativeRefcount(const char *fname, int lineno, PyObject *op)
-{
- char buf[300];
-
- PyOS_snprintf(buf, sizeof(buf),
- "%s:%i object at %p has negative ref count "
- "%" PY_FORMAT_SIZE_T "d",
- fname, lineno, op, op->ob_refcnt);
- Py_FatalError(buf);
-}
-
-#endif /* Py_REF_DEBUG */
-
-void
-Py_IncRef(PyObject *o)
-{
- Py_XINCREF(o);
-}
-
-void
-Py_DecRef(PyObject *o)
-{
- Py_XDECREF(o);
-}
-
-PyObject *
-PyObject_Init(PyObject *op, PyTypeObject *tp)
-{
- if (op == NULL)
- return PyErr_NoMemory();
- /* Any changes should be reflected in PyObject_INIT (objimpl.h) */
- op->ob_type = tp;
- _Py_NewReference(op);
- return op;
-}
-
-PyVarObject *
-PyObject_InitVar(PyVarObject *op, PyTypeObject *tp, Py_ssize_t size)
-{
- if (op == NULL)
- return (PyVarObject *) PyErr_NoMemory();
- /* Any changes should be reflected in PyObject_INIT_VAR */
- op->ob_size = size;
- op->ob_type = tp;
- _Py_NewReference((PyObject *)op);
- return op;
-}
-
-PyObject *
-_PyObject_New(PyTypeObject *tp)
-{
- PyObject *op;
- op = (PyObject *) PyObject_MALLOC(_PyObject_SIZE(tp));
- if (op == NULL)
- return PyErr_NoMemory();
- return PyObject_INIT(op, tp);
-}
-
-PyVarObject *
-_PyObject_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
-{
- PyVarObject *op;
- const size_t size = _PyObject_VAR_SIZE(tp, nitems);
- op = (PyVarObject *) PyObject_MALLOC(size);
- if (op == NULL)
- return (PyVarObject *)PyErr_NoMemory();
- return PyObject_INIT_VAR(op, tp, nitems);
-}
-
-/* for binary compatibility with 2.2 */
-#undef _PyObject_Del
-void
-_PyObject_Del(PyObject *op)
-{
- PyObject_FREE(op);
-}
-
-/* Implementation of PyObject_Print with recursion checking */
-static int
-internal_print(PyObject *op, FILE *fp, int flags, int nesting)
-{
- int ret = 0;
- if (nesting > 10) {
- PyErr_SetString(PyExc_RuntimeError, "print recursion");
- return -1;
- }
- if (PyErr_CheckSignals())
- return -1;
-#ifdef USE_STACKCHECK
- if (PyOS_CheckStack()) {
- PyErr_SetString(PyExc_MemoryError, "stack overflow");
- return -1;
- }
-#endif
- clearerr(fp); /* Clear any previous error condition */
- if (op == NULL) {
- fprintf(fp, "<nil>");
- }
- else {
- if (op->ob_refcnt <= 0)
- /* XXX(twouters) cast refcount to long until %zd is
- universally available */
- fprintf(fp, "<refcnt %ld at %p>",
- (long)op->ob_refcnt, op);
- else if (op->ob_type->tp_print == NULL) {
- PyObject *s;
- if (flags & Py_PRINT_RAW)
- s = PyObject_Str(op);
- else
- s = PyObject_Repr(op);
- if (s == NULL)
- ret = -1;
- else {
- ret = internal_print(s, fp, Py_PRINT_RAW,
- nesting+1);
- }
- Py_XDECREF(s);
- }
- else
- ret = (*op->ob_type->tp_print)(op, fp, flags);
- }
- if (ret == 0) {
- if (ferror(fp)) {
- PyErr_SetFromErrno(PyExc_IOError);
- clearerr(fp);
- ret = -1;
- }
- }
- return ret;
-}
-
-int
-PyObject_Print(PyObject *op, FILE *fp, int flags)
-{
- return internal_print(op, fp, flags, 0);
-}
-
-
-/* For debugging convenience. See Misc/gdbinit for some useful gdb hooks */
-void _PyObject_Dump(PyObject* op)
-{
- if (op == NULL)
- fprintf(stderr, "NULL\n");
- else {
- fprintf(stderr, "object : ");
- (void)PyObject_Print(op, stderr, 0);
- /* XXX(twouters) cast refcount to long until %zd is
- universally available */
- fprintf(stderr, "\n"
- "type : %s\n"
- "refcount: %ld\n"
- "address : %p\n",
- op->ob_type==NULL ? "NULL" : op->ob_type->tp_name,
- (long)op->ob_refcnt,
- op);
- }
-}
-
-PyObject *
-PyObject_Repr(PyObject *v)
-{
- if (PyErr_CheckSignals())
- return NULL;
-#ifdef USE_STACKCHECK
- if (PyOS_CheckStack()) {
- PyErr_SetString(PyExc_MemoryError, "stack overflow");
- return NULL;
- }
-#endif
- if (v == NULL)
- return PyString_FromString("<NULL>");
- else if (v->ob_type->tp_repr == NULL)
- return PyString_FromFormat("<%s object at %p>",
- v->ob_type->tp_name, v);
- else {
- PyObject *res;
- res = (*v->ob_type->tp_repr)(v);
- if (res == NULL)
- return NULL;
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(res)) {
- PyObject* str;
- str = PyUnicode_AsEncodedString(res, NULL, NULL);
- Py_DECREF(res);
- if (str)
- res = str;
- else
- return NULL;
- }
-#endif
- if (!PyString_Check(res)) {
- PyErr_Format(PyExc_TypeError,
- "__repr__ returned non-string (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
- }
-}
-
-PyObject *
-_PyObject_Str(PyObject *v)
-{
- PyObject *res;
- int type_ok;
- if (v == NULL)
- return PyString_FromString("<NULL>");
- if (PyString_CheckExact(v)) {
- Py_INCREF(v);
- return v;
- }
-#ifdef Py_USING_UNICODE
- if (PyUnicode_CheckExact(v)) {
- Py_INCREF(v);
- return v;
- }
-#endif
- if (v->ob_type->tp_str == NULL)
- return PyObject_Repr(v);
-
- res = (*v->ob_type->tp_str)(v);
- if (res == NULL)
- return NULL;
- type_ok = PyString_Check(res);
-#ifdef Py_USING_UNICODE
- type_ok = type_ok || PyUnicode_Check(res);
-#endif
- if (!type_ok) {
- PyErr_Format(PyExc_TypeError,
- "__str__ returned non-string (type %.200s)",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return NULL;
- }
- return res;
-}
-
-PyObject *
-PyObject_Str(PyObject *v)
-{
- PyObject *res = _PyObject_Str(v);
- if (res == NULL)
- return NULL;
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(res)) {
- PyObject* str;
- str = PyUnicode_AsEncodedString(res, NULL, NULL);
- Py_DECREF(res);
- if (str)
- res = str;
- else
- return NULL;
- }
-#endif
- assert(PyString_Check(res));
- return res;
-}
-
-#ifdef Py_USING_UNICODE
-PyObject *
-PyObject_Unicode(PyObject *v)
-{
- PyObject *res;
- PyObject *func;
- PyObject *str;
- static PyObject *unicodestr;
-
- if (v == NULL) {
- res = PyString_FromString("<NULL>");
- if (res == NULL)
- return NULL;
- str = PyUnicode_FromEncodedObject(res, NULL, "strict");
- Py_DECREF(res);
- return str;
- } else if (PyUnicode_CheckExact(v)) {
- Py_INCREF(v);
- return v;
- }
- /* XXX As soon as we have a tp_unicode slot, we should
- check this before trying the __unicode__
- method. */
- if (unicodestr == NULL) {
- unicodestr= PyString_InternFromString("__unicode__");
- if (unicodestr == NULL)
- return NULL;
- }
- func = PyObject_GetAttr(v, unicodestr);
- if (func != NULL) {
- res = PyEval_CallObject(func, (PyObject *)NULL);
- Py_DECREF(func);
- }
- else {
- PyErr_Clear();
- if (PyUnicode_Check(v)) {
- /* For a Unicode subtype that's didn't overwrite __unicode__,
- return a true Unicode object with the same data. */
- return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(v),
- PyUnicode_GET_SIZE(v));
- }
- if (PyString_CheckExact(v)) {
- Py_INCREF(v);
- res = v;
- }
- else {
- if (v->ob_type->tp_str != NULL)
- res = (*v->ob_type->tp_str)(v);
- else
- res = PyObject_Repr(v);
- }
- }
- if (res == NULL)
- return NULL;
- if (!PyUnicode_Check(res)) {
- str = PyUnicode_FromEncodedObject(res, NULL, "strict");
- Py_DECREF(res);
- res = str;
- }
- return res;
-}
-#endif
-
-
-/* Helper to warn about deprecated tp_compare return values. Return:
- -2 for an exception;
- -1 if v < w;
- 0 if v == w;
- 1 if v > w.
- (This function cannot return 2.)
-*/
-static int
-adjust_tp_compare(int c)
-{
- if (PyErr_Occurred()) {
- if (c != -1 && c != -2) {
- PyObject *t, *v, *tb;
- PyErr_Fetch(&t, &v, &tb);
- if (PyErr_Warn(PyExc_RuntimeWarning,
- "tp_compare didn't return -1 or -2 "
- "for exception") < 0) {
- Py_XDECREF(t);
- Py_XDECREF(v);
- Py_XDECREF(tb);
- }
- else
- PyErr_Restore(t, v, tb);
- }
- return -2;
- }
- else if (c < -1 || c > 1) {
- if (PyErr_Warn(PyExc_RuntimeWarning,
- "tp_compare didn't return -1, 0 or 1") < 0)
- return -2;
- else
- return c < -1 ? -1 : 1;
- }
- else {
- assert(c >= -1 && c <= 1);
- return c;
- }
-}
-
-
-/* Macro to get the tp_richcompare field of a type if defined */
-#define RICHCOMPARE(t) (PyType_HasFeature((t), Py_TPFLAGS_HAVE_RICHCOMPARE) \
- ? (t)->tp_richcompare : NULL)
-
-/* Map rich comparison operators to their swapped version, e.g. LT --> GT */
-int _Py_SwappedOp[] = {Py_GT, Py_GE, Py_EQ, Py_NE, Py_LT, Py_LE};
-
-/* Try a genuine rich comparison, returning an object. Return:
- NULL for exception;
- NotImplemented if this particular rich comparison is not implemented or
- undefined;
- some object not equal to NotImplemented if it is implemented
- (this latter object may not be a Boolean).
-*/
-static PyObject *
-try_rich_compare(PyObject *v, PyObject *w, int op)
-{
- richcmpfunc f;
- PyObject *res;
-
- if (v->ob_type != w->ob_type &&
- PyType_IsSubtype(w->ob_type, v->ob_type) &&
- (f = RICHCOMPARE(w->ob_type)) != NULL) {
- res = (*f)(w, v, _Py_SwappedOp[op]);
- if (res != Py_NotImplemented)
- return res;
- Py_DECREF(res);
- }
- if ((f = RICHCOMPARE(v->ob_type)) != NULL) {
- res = (*f)(v, w, op);
- if (res != Py_NotImplemented)
- return res;
- Py_DECREF(res);
- }
- if ((f = RICHCOMPARE(w->ob_type)) != NULL) {
- return (*f)(w, v, _Py_SwappedOp[op]);
- }
- res = Py_NotImplemented;
- Py_INCREF(res);
- return res;
-}
-
-/* Try a genuine rich comparison, returning an int. Return:
- -1 for exception (including the case where try_rich_compare() returns an
- object that's not a Boolean);
- 0 if the outcome is false;
- 1 if the outcome is true;
- 2 if this particular rich comparison is not implemented or undefined.
-*/
-static int
-try_rich_compare_bool(PyObject *v, PyObject *w, int op)
-{
- PyObject *res;
- int ok;
-
- if (RICHCOMPARE(v->ob_type) == NULL && RICHCOMPARE(w->ob_type) == NULL)
- return 2; /* Shortcut, avoid INCREF+DECREF */
- res = try_rich_compare(v, w, op);
- if (res == NULL)
- return -1;
- if (res == Py_NotImplemented) {
- Py_DECREF(res);
- return 2;
- }
- ok = PyObject_IsTrue(res);
- Py_DECREF(res);
- return ok;
-}
-
-/* Try rich comparisons to determine a 3-way comparison. Return:
- -2 for an exception;
- -1 if v < w;
- 0 if v == w;
- 1 if v > w;
- 2 if this particular rich comparison is not implemented or undefined.
-*/
-static int
-try_rich_to_3way_compare(PyObject *v, PyObject *w)
-{
- static struct { int op; int outcome; } tries[3] = {
- /* Try this operator, and if it is true, use this outcome: */
- {Py_EQ, 0},
- {Py_LT, -1},
- {Py_GT, 1},
- };
- int i;
-
- if (RICHCOMPARE(v->ob_type) == NULL && RICHCOMPARE(w->ob_type) == NULL)
- return 2; /* Shortcut */
-
- for (i = 0; i < 3; i++) {
- switch (try_rich_compare_bool(v, w, tries[i].op)) {
- case -1:
- return -2;
- case 1:
- return tries[i].outcome;
- }
- }
-
- return 2;
-}
-
-/* Try a 3-way comparison, returning an int. Return:
- -2 for an exception;
- -1 if v < w;
- 0 if v == w;
- 1 if v > w;
- 2 if this particular 3-way comparison is not implemented or undefined.
-*/
-static int
-try_3way_compare(PyObject *v, PyObject *w)
-{
- int c;
- cmpfunc f;
-
- /* Comparisons involving instances are given to instance_compare,
- which has the same return conventions as this function. */
-
- f = v->ob_type->tp_compare;
- if (PyInstance_Check(v))
- return (*f)(v, w);
- if (PyInstance_Check(w))
- return (*w->ob_type->tp_compare)(v, w);
-
- /* If both have the same (non-NULL) tp_compare, use it. */
- if (f != NULL && f == w->ob_type->tp_compare) {
- c = (*f)(v, w);
- return adjust_tp_compare(c);
- }
-
- /* If either tp_compare is _PyObject_SlotCompare, that's safe. */
- if (f == _PyObject_SlotCompare ||
- w->ob_type->tp_compare == _PyObject_SlotCompare)
- return _PyObject_SlotCompare(v, w);
-
- /* If we're here, v and w,
- a) are not instances;
- b) have different types or a type without tp_compare; and
- c) don't have a user-defined tp_compare.
- tp_compare implementations in C assume that both arguments
- have their type, so we give up if the coercion fails or if
- it yields types which are still incompatible (which can
- happen with a user-defined nb_coerce).
- */
- c = PyNumber_CoerceEx(&v, &w);
- if (c < 0)
- return -2;
- if (c > 0)
- return 2;
- f = v->ob_type->tp_compare;
- if (f != NULL && f == w->ob_type->tp_compare) {
- c = (*f)(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- return adjust_tp_compare(c);
- }
-
- /* No comparison defined */
- Py_DECREF(v);
- Py_DECREF(w);
- return 2;
-}
-
-/* Final fallback 3-way comparison, returning an int. Return:
- -2 if an error occurred;
- -1 if v < w;
- 0 if v == w;
- 1 if v > w.
-*/
-static int
-default_3way_compare(PyObject *v, PyObject *w)
-{
- int c;
- const char *vname, *wname;
-
- if (v->ob_type == w->ob_type) {
- /* When comparing these pointers, they must be cast to
- * integer types (i.e. Py_uintptr_t, our spelling of C9X's
- * uintptr_t). ANSI specifies that pointer compares other
- * than == and != to non-related structures are undefined.
- */
- Py_uintptr_t vv = (Py_uintptr_t)v;
- Py_uintptr_t ww = (Py_uintptr_t)w;
- return (vv < ww) ? -1 : (vv > ww) ? 1 : 0;
- }
-
- /* None is smaller than anything */
- if (v == Py_None)
- return -1;
- if (w == Py_None)
- return 1;
-
- /* different type: compare type names; numbers are smaller */
- if (PyNumber_Check(v))
- vname = "";
- else
- vname = v->ob_type->tp_name;
- if (PyNumber_Check(w))
- wname = "";
- else
- wname = w->ob_type->tp_name;
- c = strcmp(vname, wname);
- if (c < 0)
- return -1;
- if (c > 0)
- return 1;
- /* Same type name, or (more likely) incomparable numeric types */
- return ((Py_uintptr_t)(v->ob_type) < (
- Py_uintptr_t)(w->ob_type)) ? -1 : 1;
-}
-
-/* Do a 3-way comparison, by hook or by crook. Return:
- -2 for an exception (but see below);
- -1 if v < w;
- 0 if v == w;
- 1 if v > w;
- BUT: if the object implements a tp_compare function, it returns
- whatever this function returns (whether with an exception or not).
-*/
-static int
-do_cmp(PyObject *v, PyObject *w)
-{
- int c;
- cmpfunc f;
-
- if (v->ob_type == w->ob_type
- && (f = v->ob_type->tp_compare) != NULL) {
- c = (*f)(v, w);
- if (PyInstance_Check(v)) {
- /* Instance tp_compare has a different signature.
- But if it returns undefined we fall through. */
- if (c != 2)
- return c;
- /* Else fall through to try_rich_to_3way_compare() */
- }
- else
- return adjust_tp_compare(c);
- }
- /* We only get here if one of the following is true:
- a) v and w have different types
- b) v and w have the same type, which doesn't have tp_compare
- c) v and w are instances, and either __cmp__ is not defined or
- __cmp__ returns NotImplemented
- */
- c = try_rich_to_3way_compare(v, w);
- if (c < 2)
- return c;
- c = try_3way_compare(v, w);
- if (c < 2)
- return c;
- return default_3way_compare(v, w);
-}
-
-/* Compare v to w. Return
- -1 if v < w or exception (PyErr_Occurred() true in latter case).
- 0 if v == w.
- 1 if v > w.
- XXX The docs (C API manual) say the return value is undefined in case
- XXX of error.
-*/
-int
-PyObject_Compare(PyObject *v, PyObject *w)
-{
- int result;
-
- if (v == NULL || w == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (v == w)
- return 0;
- if (Py_EnterRecursiveCall(" in cmp"))
- return -1;
- result = do_cmp(v, w);
- Py_LeaveRecursiveCall();
- return result < 0 ? -1 : result;
-}
-
-/* Return (new reference to) Py_True or Py_False. */
-static PyObject *
-convert_3way_to_object(int op, int c)
-{
- PyObject *result;
- switch (op) {
- case Py_LT: c = c < 0; break;
- case Py_LE: c = c <= 0; break;
- case Py_EQ: c = c == 0; break;
- case Py_NE: c = c != 0; break;
- case Py_GT: c = c > 0; break;
- case Py_GE: c = c >= 0; break;
- }
- result = c ? Py_True : Py_False;
- Py_INCREF(result);
- return result;
-}
-
-/* We want a rich comparison but don't have one. Try a 3-way cmp instead.
- Return
- NULL if error
- Py_True if v op w
- Py_False if not (v op w)
-*/
-static PyObject *
-try_3way_to_rich_compare(PyObject *v, PyObject *w, int op)
-{
- int c;
-
- c = try_3way_compare(v, w);
- if (c >= 2)
- c = default_3way_compare(v, w);
- if (c <= -2)
- return NULL;
- return convert_3way_to_object(op, c);
-}
-
-/* Do rich comparison on v and w. Return
- NULL if error
- Else a new reference to an object other than Py_NotImplemented, usually(?):
- Py_True if v op w
- Py_False if not (v op w)
-*/
-static PyObject *
-do_richcmp(PyObject *v, PyObject *w, int op)
-{
- PyObject *res;
-
- res = try_rich_compare(v, w, op);
- if (res != Py_NotImplemented)
- return res;
- Py_DECREF(res);
-
- return try_3way_to_rich_compare(v, w, op);
-}
-
-/* Return:
- NULL for exception;
- some object not equal to NotImplemented if it is implemented
- (this latter object may not be a Boolean).
-*/
-PyObject *
-PyObject_RichCompare(PyObject *v, PyObject *w, int op)
-{
- PyObject *res;
-
- assert(Py_LT <= op && op <= Py_GE);
- if (Py_EnterRecursiveCall(" in cmp"))
- return NULL;
-
- /* If the types are equal, and not old-style instances, try to
- get out cheap (don't bother with coercions etc.). */
- if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
- cmpfunc fcmp;
- richcmpfunc frich = RICHCOMPARE(v->ob_type);
- /* If the type has richcmp, try it first. try_rich_compare
- tries it two-sided, which is not needed since we've a
- single type only. */
- if (frich != NULL) {
- res = (*frich)(v, w, op);
- if (res != Py_NotImplemented)
- goto Done;
- Py_DECREF(res);
- }
- /* No richcmp, or this particular richmp not implemented.
- Try 3-way cmp. */
- fcmp = v->ob_type->tp_compare;
- if (fcmp != NULL) {
- int c = (*fcmp)(v, w);
- c = adjust_tp_compare(c);
- if (c == -2) {
- res = NULL;
- goto Done;
- }
- res = convert_3way_to_object(op, c);
- goto Done;
- }
- }
-
- /* Fast path not taken, or couldn't deliver a useful result. */
- res = do_richcmp(v, w, op);
-Done:
- Py_LeaveRecursiveCall();
- return res;
-}
-
-/* Return -1 if error; 1 if v op w; 0 if not (v op w). */
-int
-PyObject_RichCompareBool(PyObject *v, PyObject *w, int op)
-{
- PyObject *res;
- int ok;
-
- /* Quick result when objects are the same.
- Guarantees that identity implies equality. */
- if (v == w) {
- if (op == Py_EQ)
- return 1;
- else if (op == Py_NE)
- return 0;
- }
-
- res = PyObject_RichCompare(v, w, op);
- if (res == NULL)
- return -1;
- if (PyBool_Check(res))
- ok = (res == Py_True);
- else
- ok = PyObject_IsTrue(res);
- Py_DECREF(res);
- return ok;
-}
-
-/* Set of hash utility functions to help maintaining the invariant that
- if a==b then hash(a)==hash(b)
-
- All the utility functions (_Py_Hash*()) return "-1" to signify an error.
-*/
-
-long
-_Py_HashDouble(double v)
-{
- double intpart, fractpart;
- int expo;
- long hipart;
- long x; /* the final hash value */
- /* This is designed so that Python numbers of different types
- * that compare equal hash to the same value; otherwise comparisons
- * of mapping keys will turn out weird.
- */
-
- fractpart = modf(v, &intpart);
- if (fractpart == 0.0) {
- /* This must return the same hash as an equal int or long. */
- if (intpart > LONG_MAX || -intpart > LONG_MAX) {
- /* Convert to long and use its hash. */
- PyObject *plong; /* converted to Python long */
- if (Py_IS_INFINITY(intpart))
- /* can't convert to long int -- arbitrary */
- v = v < 0 ? -271828.0 : 314159.0;
- plong = PyLong_FromDouble(v);
- if (plong == NULL)
- return -1;
- x = PyObject_Hash(plong);
- Py_DECREF(plong);
- return x;
- }
- /* Fits in a C long == a Python int, so is its own hash. */
- x = (long)intpart;
- if (x == -1)
- x = -2;
- return x;
- }
- /* The fractional part is non-zero, so we don't have to worry about
- * making this match the hash of some other type.
- * Use frexp to get at the bits in the double.
- * Since the VAX D double format has 56 mantissa bits, which is the
- * most of any double format in use, each of these parts may have as
- * many as (but no more than) 56 significant bits.
- * So, assuming sizeof(long) >= 4, each part can be broken into two
- * longs; frexp and multiplication are used to do that.
- * Also, since the Cray double format has 15 exponent bits, which is
- * the most of any double format in use, shifting the exponent field
- * left by 15 won't overflow a long (again assuming sizeof(long) >= 4).
- */
- v = frexp(v, &expo);
- v *= 2147483648.0; /* 2**31 */
- hipart = (long)v; /* take the top 32 bits */
- v = (v - (double)hipart) * 2147483648.0; /* get the next 32 bits */
- x = hipart + (long)v + (expo << 15);
- if (x == -1)
- x = -2;
- return x;
-}
-
-long
-_Py_HashPointer(void *p)
-{
-#if SIZEOF_LONG >= SIZEOF_VOID_P
- return (long)p;
-#else
- /* convert to a Python long and hash that */
- PyObject* longobj;
- long x;
-
- if ((longobj = PyLong_FromVoidPtr(p)) == NULL) {
- x = -1;
- goto finally;
- }
- x = PyObject_Hash(longobj);
-
-finally:
- Py_XDECREF(longobj);
- return x;
-#endif
-}
-
-
-long
-PyObject_Hash(PyObject *v)
-{
- PyTypeObject *tp = v->ob_type;
- if (tp->tp_hash != NULL)
- return (*tp->tp_hash)(v);
- if (tp->tp_compare == NULL && RICHCOMPARE(tp) == NULL) {
- return _Py_HashPointer(v); /* Use address as hash value */
- }
- /* If there's a cmp but no hash defined, the object can't be hashed */
- PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",
- v->ob_type->tp_name);
- return -1;
-}
-
-PyObject *
-PyObject_GetAttrString(PyObject *v, const char *name)
-{
- PyObject *w, *res;
-
- if (v->ob_type->tp_getattr != NULL)
- return (*v->ob_type->tp_getattr)(v, (char*)name);
- w = PyString_InternFromString(name);
- if (w == NULL)
- return NULL;
- res = PyObject_GetAttr(v, w);
- Py_XDECREF(w);
- return res;
-}
-
-int
-PyObject_HasAttrString(PyObject *v, const char *name)
-{
- PyObject *res = PyObject_GetAttrString(v, name);
- if (res != NULL) {
- Py_DECREF(res);
- return 1;
- }
- PyErr_Clear();
- return 0;
-}
-
-int
-PyObject_SetAttrString(PyObject *v, const char *name, PyObject *w)
-{
- PyObject *s;
- int res;
-
- if (v->ob_type->tp_setattr != NULL)
- return (*v->ob_type->tp_setattr)(v, (char*)name, w);
- s = PyString_InternFromString(name);
- if (s == NULL)
- return -1;
- res = PyObject_SetAttr(v, s, w);
- Py_XDECREF(s);
- return res;
-}
-
-PyObject *
-PyObject_GetAttr(PyObject *v, PyObject *name)
-{
- PyTypeObject *tp = v->ob_type;
-
- if (!PyString_Check(name)) {
-#ifdef Py_USING_UNICODE
- /* The Unicode to string conversion is done here because the
- existing tp_getattro slots expect a string object as name
- and we wouldn't want to break those. */
- if (PyUnicode_Check(name)) {
- name = _PyUnicode_AsDefaultEncodedString(name, NULL);
- if (name == NULL)
- return NULL;
- }
- else
-#endif
- {
- PyErr_Format(PyExc_TypeError,
- "attribute name must be string, not '%.200s'",
- name->ob_type->tp_name);
- return NULL;
- }
- }
- if (tp->tp_getattro != NULL)
- return (*tp->tp_getattro)(v, name);
- if (tp->tp_getattr != NULL)
- return (*tp->tp_getattr)(v, PyString_AS_STRING(name));
- PyErr_Format(PyExc_AttributeError,
- "'%.50s' object has no attribute '%.400s'",
- tp->tp_name, PyString_AS_STRING(name));
- return NULL;
-}
-
-int
-PyObject_HasAttr(PyObject *v, PyObject *name)
-{
- PyObject *res = PyObject_GetAttr(v, name);
- if (res != NULL) {
- Py_DECREF(res);
- return 1;
- }
- PyErr_Clear();
- return 0;
-}
-
-int
-PyObject_SetAttr(PyObject *v, PyObject *name, PyObject *value)
-{
- PyTypeObject *tp = v->ob_type;
- int err;
-
- if (!PyString_Check(name)){
-#ifdef Py_USING_UNICODE
- /* The Unicode to string conversion is done here because the
- existing tp_setattro slots expect a string object as name
- and we wouldn't want to break those. */
- if (PyUnicode_Check(name)) {
- name = PyUnicode_AsEncodedString(name, NULL, NULL);
- if (name == NULL)
- return -1;
- }
- else
-#endif
- {
- PyErr_Format(PyExc_TypeError,
- "attribute name must be string, not '%.200s'",
- name->ob_type->tp_name);
- return -1;
- }
- }
- else
- Py_INCREF(name);
-
- PyString_InternInPlace(&name);
- if (tp->tp_setattro != NULL) {
- err = (*tp->tp_setattro)(v, name, value);
- Py_DECREF(name);
- return err;
- }
- if (tp->tp_setattr != NULL) {
- err = (*tp->tp_setattr)(v, PyString_AS_STRING(name), value);
- Py_DECREF(name);
- return err;
- }
- Py_DECREF(name);
- if (tp->tp_getattr == NULL && tp->tp_getattro == NULL)
- PyErr_Format(PyExc_TypeError,
- "'%.100s' object has no attributes "
- "(%s .%.100s)",
- tp->tp_name,
- value==NULL ? "del" : "assign to",
- PyString_AS_STRING(name));
- else
- PyErr_Format(PyExc_TypeError,
- "'%.100s' object has only read-only attributes "
- "(%s .%.100s)",
- tp->tp_name,
- value==NULL ? "del" : "assign to",
- PyString_AS_STRING(name));
- return -1;
-}
-
-/* Helper to get a pointer to an object's __dict__ slot, if any */
-
-PyObject **
-_PyObject_GetDictPtr(PyObject *obj)
-{
- Py_ssize_t dictoffset;
- PyTypeObject *tp = obj->ob_type;
-
- if (!(tp->tp_flags & Py_TPFLAGS_HAVE_CLASS))
- return NULL;
- dictoffset = tp->tp_dictoffset;
- if (dictoffset == 0)
- return NULL;
- if (dictoffset < 0) {
- Py_ssize_t tsize;
- size_t size;
-
- tsize = ((PyVarObject *)obj)->ob_size;
- if (tsize < 0)
- tsize = -tsize;
- size = _PyObject_VAR_SIZE(tp, tsize);
-
- dictoffset += (long)size;
- assert(dictoffset > 0);
- assert(dictoffset % SIZEOF_VOID_P == 0);
- }
- return (PyObject **) ((char *)obj + dictoffset);
-}
-
-PyObject *
-PyObject_SelfIter(PyObject *obj)
-{
- Py_INCREF(obj);
- return obj;
-}
-
-/* Generic GetAttr functions - put these in your tp_[gs]etattro slot */
-
-PyObject *
-PyObject_GenericGetAttr(PyObject *obj, PyObject *name)
-{
- PyTypeObject *tp = obj->ob_type;
- PyObject *descr = NULL;
- PyObject *res = NULL;
- descrgetfunc f;
- Py_ssize_t dictoffset;
- PyObject **dictptr;
-
- if (!PyString_Check(name)){
-#ifdef Py_USING_UNICODE
- /* The Unicode to string conversion is done here because the
- existing tp_setattro slots expect a string object as name
- and we wouldn't want to break those. */
- if (PyUnicode_Check(name)) {
- name = PyUnicode_AsEncodedString(name, NULL, NULL);
- if (name == NULL)
- return NULL;
- }
- else
-#endif
- {
- PyErr_Format(PyExc_TypeError,
- "attribute name must be string, not '%.200s'",
- name->ob_type->tp_name);
- return NULL;
- }
- }
- else
- Py_INCREF(name);
-
- if (tp->tp_dict == NULL) {
- if (PyType_Ready(tp) < 0)
- goto done;
- }
-
- /* Inline _PyType_Lookup */
- {
- Py_ssize_t i, n;
- PyObject *mro, *base, *dict;
-
- /* Look in tp_dict of types in MRO */
- mro = tp->tp_mro;
- assert(mro != NULL);
- assert(PyTuple_Check(mro));
- n = PyTuple_GET_SIZE(mro);
- for (i = 0; i < n; i++) {
- base = PyTuple_GET_ITEM(mro, i);
- if (PyClass_Check(base))
- dict = ((PyClassObject *)base)->cl_dict;
- else {
- assert(PyType_Check(base));
- dict = ((PyTypeObject *)base)->tp_dict;
- }
- assert(dict && PyDict_Check(dict));
- descr = PyDict_GetItem(dict, name);
- if (descr != NULL)
- break;
- }
- }
-
- Py_XINCREF(descr);
-
- f = NULL;
- if (descr != NULL &&
- PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) {
- f = descr->ob_type->tp_descr_get;
- if (f != NULL && PyDescr_IsData(descr)) {
- res = f(descr, obj, (PyObject *)obj->ob_type);
- Py_DECREF(descr);
- goto done;
- }
- }
-
- /* Inline _PyObject_GetDictPtr */
- dictoffset = tp->tp_dictoffset;
- if (dictoffset != 0) {
- PyObject *dict;
- if (dictoffset < 0) {
- Py_ssize_t tsize;
- size_t size;
-
- tsize = ((PyVarObject *)obj)->ob_size;
- if (tsize < 0)
- tsize = -tsize;
- size = _PyObject_VAR_SIZE(tp, tsize);
-
- dictoffset += (long)size;
- assert(dictoffset > 0);
- assert(dictoffset % SIZEOF_VOID_P == 0);
- }
- dictptr = (PyObject **) ((char *)obj + dictoffset);
- dict = *dictptr;
- if (dict != NULL) {
- res = PyDict_GetItem(dict, name);
- if (res != NULL) {
- Py_INCREF(res);
- Py_XDECREF(descr);
- goto done;
- }
- }
- }
-
- if (f != NULL) {
- res = f(descr, obj, (PyObject *)obj->ob_type);
- Py_DECREF(descr);
- goto done;
- }
-
- if (descr != NULL) {
- res = descr;
- /* descr was already increfed above */
- goto done;
- }
-
- PyErr_Format(PyExc_AttributeError,
- "'%.50s' object has no attribute '%.400s'",
- tp->tp_name, PyString_AS_STRING(name));
- done:
- Py_DECREF(name);
- return res;
-}
-
-int
-PyObject_GenericSetAttr(PyObject *obj, PyObject *name, PyObject *value)
-{
- PyTypeObject *tp = obj->ob_type;
- PyObject *descr;
- descrsetfunc f;
- PyObject **dictptr;
- int res = -1;
-
- if (!PyString_Check(name)){
-#ifdef Py_USING_UNICODE
- /* The Unicode to string conversion is done here because the
- existing tp_setattro slots expect a string object as name
- and we wouldn't want to break those. */
- if (PyUnicode_Check(name)) {
- name = PyUnicode_AsEncodedString(name, NULL, NULL);
- if (name == NULL)
- return -1;
- }
- else
-#endif
- {
- PyErr_Format(PyExc_TypeError,
- "attribute name must be string, not '%.200s'",
- name->ob_type->tp_name);
- return -1;
- }
- }
- else
- Py_INCREF(name);
-
- if (tp->tp_dict == NULL) {
- if (PyType_Ready(tp) < 0)
- goto done;
- }
-
- descr = _PyType_Lookup(tp, name);
- f = NULL;
- if (descr != NULL &&
- PyType_HasFeature(descr->ob_type, Py_TPFLAGS_HAVE_CLASS)) {
- f = descr->ob_type->tp_descr_set;
- if (f != NULL && PyDescr_IsData(descr)) {
- res = f(descr, obj, value);
- goto done;
- }
- }
-
- dictptr = _PyObject_GetDictPtr(obj);
- if (dictptr != NULL) {
- PyObject *dict = *dictptr;
- if (dict == NULL && value != NULL) {
- dict = PyDict_New();
- if (dict == NULL)
- goto done;
- *dictptr = dict;
- }
- if (dict != NULL) {
- if (value == NULL)
- res = PyDict_DelItem(dict, name);
- else
- res = PyDict_SetItem(dict, name, value);
- if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
- PyErr_SetObject(PyExc_AttributeError, name);
- goto done;
- }
- }
-
- if (f != NULL) {
- res = f(descr, obj, value);
- goto done;
- }
-
- if (descr == NULL) {
- PyErr_Format(PyExc_AttributeError,
- "'%.100s' object has no attribute '%.200s'",
- tp->tp_name, PyString_AS_STRING(name));
- goto done;
- }
-
- PyErr_Format(PyExc_AttributeError,
- "'%.50s' object attribute '%.400s' is read-only",
- tp->tp_name, PyString_AS_STRING(name));
- done:
- Py_DECREF(name);
- return res;
-}
-
-/* Test a value used as condition, e.g., in a for or if statement.
- Return -1 if an error occurred */
-
-int
-PyObject_IsTrue(PyObject *v)
-{
- Py_ssize_t res;
- if (v == Py_True)
- return 1;
- if (v == Py_False)
- return 0;
- if (v == Py_None)
- return 0;
- else if (v->ob_type->tp_as_number != NULL &&
- v->ob_type->tp_as_number->nb_nonzero != NULL)
- res = (*v->ob_type->tp_as_number->nb_nonzero)(v);
- else if (v->ob_type->tp_as_mapping != NULL &&
- v->ob_type->tp_as_mapping->mp_length != NULL)
- res = (*v->ob_type->tp_as_mapping->mp_length)(v);
- else if (v->ob_type->tp_as_sequence != NULL &&
- v->ob_type->tp_as_sequence->sq_length != NULL)
- res = (*v->ob_type->tp_as_sequence->sq_length)(v);
- else
- return 1;
- /* if it is negative, it should be either -1 or -2 */
- return (res > 0) ? 1 : Py_SAFE_DOWNCAST(res, Py_ssize_t, int);
-}
-
-/* equivalent of 'not v'
- Return -1 if an error occurred */
-
-int
-PyObject_Not(PyObject *v)
-{
- int res;
- res = PyObject_IsTrue(v);
- if (res < 0)
- return res;
- return res == 0;
-}
-
-/* Coerce two numeric types to the "larger" one.
- Increment the reference count on each argument.
- Return value:
- -1 if an error occurred;
- 0 if the coercion succeeded (and then the reference counts are increased);
- 1 if no coercion is possible (and no error is raised).
-*/
-int
-PyNumber_CoerceEx(PyObject **pv, PyObject **pw)
-{
- register PyObject *v = *pv;
- register PyObject *w = *pw;
- int res;
-
- /* Shortcut only for old-style types */
- if (v->ob_type == w->ob_type &&
- !PyType_HasFeature(v->ob_type, Py_TPFLAGS_CHECKTYPES))
- {
- Py_INCREF(v);
- Py_INCREF(w);
- return 0;
- }
- if (v->ob_type->tp_as_number && v->ob_type->tp_as_number->nb_coerce) {
- res = (*v->ob_type->tp_as_number->nb_coerce)(pv, pw);
- if (res <= 0)
- return res;
- }
- if (w->ob_type->tp_as_number && w->ob_type->tp_as_number->nb_coerce) {
- res = (*w->ob_type->tp_as_number->nb_coerce)(pw, pv);
- if (res <= 0)
- return res;
- }
- return 1;
-}
-
-/* Coerce two numeric types to the "larger" one.
- Increment the reference count on each argument.
- Return -1 and raise an exception if no coercion is possible
- (and then no reference count is incremented).
-*/
-int
-PyNumber_Coerce(PyObject **pv, PyObject **pw)
-{
- int err = PyNumber_CoerceEx(pv, pw);
- if (err <= 0)
- return err;
- PyErr_SetString(PyExc_TypeError, "number coercion failed");
- return -1;
-}
-
-
-/* Test whether an object can be called */
-
-int
-PyCallable_Check(PyObject *x)
-{
- if (x == NULL)
- return 0;
- if (PyInstance_Check(x)) {
- PyObject *call = PyObject_GetAttrString(x, "__call__");
- if (call == NULL) {
- PyErr_Clear();
- return 0;
- }
- /* Could test recursively but don't, for fear of endless
- recursion if some joker sets self.__call__ = self */
- Py_DECREF(call);
- return 1;
- }
- else {
- return x->ob_type->tp_call != NULL;
- }
-}
-
-/* Helper for PyObject_Dir.
- Merge the __dict__ of aclass into dict, and recursively also all
- the __dict__s of aclass's base classes. The order of merging isn't
- defined, as it's expected that only the final set of dict keys is
- interesting.
- Return 0 on success, -1 on error.
-*/
-
-static int
-merge_class_dict(PyObject* dict, PyObject* aclass)
-{
- PyObject *classdict;
- PyObject *bases;
-
- assert(PyDict_Check(dict));
- assert(aclass);
-
- /* Merge in the type's dict (if any). */
- classdict = PyObject_GetAttrString(aclass, "__dict__");
- if (classdict == NULL)
- PyErr_Clear();
- else {
- int status = PyDict_Update(dict, classdict);
- Py_DECREF(classdict);
- if (status < 0)
- return -1;
- }
-
- /* Recursively merge in the base types' (if any) dicts. */
- bases = PyObject_GetAttrString(aclass, "__bases__");
- if (bases == NULL)
- PyErr_Clear();
- else {
- /* We have no guarantee that bases is a real tuple */
- Py_ssize_t i, n;
- n = PySequence_Size(bases); /* This better be right */
- if (n < 0)
- PyErr_Clear();
- else {
- for (i = 0; i < n; i++) {
- int status;
- PyObject *base = PySequence_GetItem(bases, i);
- if (base == NULL) {
- Py_DECREF(bases);
- return -1;
- }
- status = merge_class_dict(dict, base);
- Py_DECREF(base);
- if (status < 0) {
- Py_DECREF(bases);
- return -1;
- }
- }
- }
- Py_DECREF(bases);
- }
- return 0;
-}
-
-/* Helper for PyObject_Dir.
- If obj has an attr named attrname that's a list, merge its string
- elements into keys of dict.
- Return 0 on success, -1 on error. Errors due to not finding the attr,
- or the attr not being a list, are suppressed.
-*/
-
-static int
-merge_list_attr(PyObject* dict, PyObject* obj, const char *attrname)
-{
- PyObject *list;
- int result = 0;
-
- assert(PyDict_Check(dict));
- assert(obj);
- assert(attrname);
-
- list = PyObject_GetAttrString(obj, attrname);
- if (list == NULL)
- PyErr_Clear();
-
- else if (PyList_Check(list)) {
- int i;
- for (i = 0; i < PyList_GET_SIZE(list); ++i) {
- PyObject *item = PyList_GET_ITEM(list, i);
- if (PyString_Check(item)) {
- result = PyDict_SetItem(dict, item, Py_None);
- if (result < 0)
- break;
- }
- }
- }
-
- Py_XDECREF(list);
- return result;
-}
-
-/* Like __builtin__.dir(arg). See bltinmodule.c's builtin_dir for the
- docstring, which should be kept in synch with this implementation. */
-
-PyObject *
-PyObject_Dir(PyObject *arg)
-{
- /* Set exactly one of these non-NULL before the end. */
- PyObject *result = NULL; /* result list */
- PyObject *masterdict = NULL; /* result is masterdict.keys() */
-
- /* If NULL arg, return the locals. */
- if (arg == NULL) {
- PyObject *locals = PyEval_GetLocals();
- if (locals == NULL)
- goto error;
- result = PyMapping_Keys(locals);
- if (result == NULL)
- goto error;
- }
-
- /* Elif this is some form of module, we only want its dict. */
- else if (PyModule_Check(arg)) {
- masterdict = PyObject_GetAttrString(arg, "__dict__");
- if (masterdict == NULL)
- goto error;
- if (!PyDict_Check(masterdict)) {
- PyErr_SetString(PyExc_TypeError,
- "module.__dict__ is not a dictionary");
- goto error;
- }
- }
-
- /* Elif some form of type or class, grab its dict and its bases.
- We deliberately don't suck up its __class__, as methods belonging
- to the metaclass would probably be more confusing than helpful. */
- else if (PyType_Check(arg) || PyClass_Check(arg)) {
- masterdict = PyDict_New();
- if (masterdict == NULL)
- goto error;
- if (merge_class_dict(masterdict, arg) < 0)
- goto error;
- }
-
- /* Else look at its dict, and the attrs reachable from its class. */
- else {
- PyObject *itsclass;
- /* Create a dict to start with. CAUTION: Not everything
- responding to __dict__ returns a dict! */
- masterdict = PyObject_GetAttrString(arg, "__dict__");
- if (masterdict == NULL) {
- PyErr_Clear();
- masterdict = PyDict_New();
- }
- else if (!PyDict_Check(masterdict)) {
- Py_DECREF(masterdict);
- masterdict = PyDict_New();
- }
- else {
- /* The object may have returned a reference to its
- dict, so copy it to avoid mutating it. */
- PyObject *temp = PyDict_Copy(masterdict);
- Py_DECREF(masterdict);
- masterdict = temp;
- }
- if (masterdict == NULL)
- goto error;
-
- /* Merge in __members__ and __methods__ (if any).
- XXX Would like this to go away someday; for now, it's
- XXX needed to get at im_self etc of method objects. */
- if (merge_list_attr(masterdict, arg, "__members__") < 0)
- goto error;
- if (merge_list_attr(masterdict, arg, "__methods__") < 0)
- goto error;
-
- /* Merge in attrs reachable from its class.
- CAUTION: Not all objects have a __class__ attr. */
- itsclass = PyObject_GetAttrString(arg, "__class__");
- if (itsclass == NULL)
- PyErr_Clear();
- else {
- int status = merge_class_dict(masterdict, itsclass);
- Py_DECREF(itsclass);
- if (status < 0)
- goto error;
- }
- }
-
- assert((result == NULL) ^ (masterdict == NULL));
- if (masterdict != NULL) {
- /* The result comes from its keys. */
- assert(result == NULL);
- result = PyDict_Keys(masterdict);
- if (result == NULL)
- goto error;
- }
-
- assert(result);
- if (!PyList_Check(result)) {
- PyErr_Format(PyExc_TypeError,
- "Expected keys() to be a list, not '%.200s'",
- result->ob_type->tp_name);
- goto error;
- }
- if (PyList_Sort(result) != 0)
- goto error;
- else
- goto normal_return;
-
- error:
- Py_XDECREF(result);
- result = NULL;
- /* fall through */
- normal_return:
- Py_XDECREF(masterdict);
- return result;
-}
-
-/*
-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,
-so there is exactly one (which is indestructible, by the way).
-(XXX This type and the type of NotImplemented below should be unified.)
-*/
-
-/* ARGSUSED */
-static PyObject *
-none_repr(PyObject *op)
-{
- return PyString_FromString("None");
-}
-
-/* ARGUSED */
-static void
-none_dealloc(PyObject* ignore)
-{
- /* This should never get called, but we also don't want to SEGV if
- * we accidently decref None out of existance.
- */
- Py_FatalError("deallocating None");
-}
-
-
-static PyTypeObject PyNone_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "NoneType",
- 0,
- 0,
- none_dealloc, /*tp_dealloc*/ /*never called*/
- 0, /*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*/
- 0, /*tp_hash */
-};
-
-PyObject _Py_NoneStruct = {
- PyObject_HEAD_INIT(&PyNone_Type)
-};
-
-/* NotImplemented is an object that can be used to signal that an
- operation is not implemented for the given type combination. */
-
-static PyObject *
-NotImplemented_repr(PyObject *op)
-{
- return PyString_FromString("NotImplemented");
-}
-
-static PyTypeObject PyNotImplemented_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "NotImplementedType",
- 0,
- 0,
- none_dealloc, /*tp_dealloc*/ /*never called*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- NotImplemented_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash */
-};
-
-PyObject _Py_NotImplementedStruct = {
- PyObject_HEAD_INIT(&PyNotImplemented_Type)
-};
-
-void
-_Py_ReadyTypes(void)
-{
- if (PyType_Ready(&PyType_Type) < 0)
- Py_FatalError("Can't initialize 'type'");
-
- if (PyType_Ready(&_PyWeakref_RefType) < 0)
- Py_FatalError("Can't initialize 'weakref'");
-
- if (PyType_Ready(&PyBool_Type) < 0)
- Py_FatalError("Can't initialize 'bool'");
-
- if (PyType_Ready(&PyString_Type) < 0)
- Py_FatalError("Can't initialize 'str'");
-
- if (PyType_Ready(&PyList_Type) < 0)
- Py_FatalError("Can't initialize 'list'");
-
- if (PyType_Ready(&PyNone_Type) < 0)
- Py_FatalError("Can't initialize type(None)");
-
- if (PyType_Ready(&PyNotImplemented_Type) < 0)
- Py_FatalError("Can't initialize type(NotImplemented)");
-}
-
-
-#ifdef Py_TRACE_REFS
-
-void
-_Py_NewReference(PyObject *op)
-{
- _Py_INC_REFTOTAL;
- op->ob_refcnt = 1;
- _Py_AddToAllObjects(op, 1);
- _Py_INC_TPALLOCS(op);
-}
-
-void
-_Py_ForgetReference(register PyObject *op)
-{
-#ifdef SLOW_UNREF_CHECK
- register PyObject *p;
-#endif
- if (op->ob_refcnt < 0)
- Py_FatalError("UNREF negative refcnt");
- if (op == &refchain ||
- op->_ob_prev->_ob_next != op || op->_ob_next->_ob_prev != op)
- Py_FatalError("UNREF invalid object");
-#ifdef SLOW_UNREF_CHECK
- for (p = refchain._ob_next; p != &refchain; p = p->_ob_next) {
- if (p == op)
- break;
- }
- if (p == &refchain) /* Not found */
- Py_FatalError("UNREF unknown object");
-#endif
- op->_ob_next->_ob_prev = op->_ob_prev;
- op->_ob_prev->_ob_next = op->_ob_next;
- op->_ob_next = op->_ob_prev = NULL;
- _Py_INC_TPFREES(op);
-}
-
-void
-_Py_Dealloc(PyObject *op)
-{
- destructor dealloc = op->ob_type->tp_dealloc;
- _Py_ForgetReference(op);
- (*dealloc)(op);
-}
-
-/* Print all live objects. Because PyObject_Print is called, the
- * interpreter must be in a healthy state.
- */
-void
-_Py_PrintReferences(FILE *fp)
-{
- PyObject *op;
- fprintf(fp, "Remaining objects:\n");
- for (op = refchain._ob_next; op != &refchain; op = op->_ob_next) {
- fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] ", op, op->ob_refcnt);
- if (PyObject_Print(op, fp, 0) != 0)
- PyErr_Clear();
- putc('\n', fp);
- }
-}
-
-/* Print the addresses of all live objects. Unlike _Py_PrintReferences, this
- * doesn't make any calls to the Python C API, so is always safe to call.
- */
-void
-_Py_PrintReferenceAddresses(FILE *fp)
-{
- PyObject *op;
- fprintf(fp, "Remaining object addresses:\n");
- for (op = refchain._ob_next; op != &refchain; op = op->_ob_next)
- fprintf(fp, "%p [%" PY_FORMAT_SIZE_T "d] %s\n", op,
- op->ob_refcnt, op->ob_type->tp_name);
-}
-
-PyObject *
-_Py_GetObjects(PyObject *self, PyObject *args)
-{
- int i, n;
- PyObject *t = NULL;
- PyObject *res, *op;
-
- if (!PyArg_ParseTuple(args, "i|O", &n, &t))
- return NULL;
- op = refchain._ob_next;
- res = PyList_New(0);
- if (res == NULL)
- return NULL;
- for (i = 0; (n == 0 || i < n) && op != &refchain; i++) {
- while (op == self || op == args || op == res || op == t ||
- (t != NULL && op->ob_type != (PyTypeObject *) t)) {
- op = op->_ob_next;
- if (op == &refchain)
- return res;
- }
- if (PyList_Append(res, op) < 0) {
- Py_DECREF(res);
- return NULL;
- }
- op = op->_ob_next;
- }
- return res;
-}
-
-#endif
-
-
-/* Hack to force loading of cobject.o */
-PyTypeObject *_Py_cobject_hack = &PyCObject_Type;
-
-
-/* Hack to force loading of abstract.o */
-Py_ssize_t (*_Py_abstract_hack)(PyObject *) = PyObject_Size;
-
-
-/* Python's malloc wrappers (see pymem.h) */
-
-void *
-PyMem_Malloc(size_t nbytes)
-{
- return PyMem_MALLOC(nbytes);
-}
-
-void *
-PyMem_Realloc(void *p, size_t nbytes)
-{
- return PyMem_REALLOC(p, nbytes);
-}
-
-void
-PyMem_Free(void *p)
-{
- PyMem_FREE(p);
-}
-
-
-/* These methods are used to control infinite recursion in repr, str, print,
- etc. Container objects that may recursively contain themselves,
- e.g. builtin dictionaries and lists, should used Py_ReprEnter() and
- Py_ReprLeave() to avoid infinite recursion.
-
- Py_ReprEnter() returns 0 the first time it is called for a particular
- object and 1 every time thereafter. It returns -1 if an exception
- occurred. Py_ReprLeave() has no return value.
-
- See dictobject.c and listobject.c for examples of use.
-*/
-
-#define KEY "Py_Repr"
-
-int
-Py_ReprEnter(PyObject *obj)
-{
- PyObject *dict;
- PyObject *list;
- Py_ssize_t i;
-
- dict = PyThreadState_GetDict();
- if (dict == NULL)
- return 0;
- list = PyDict_GetItemString(dict, KEY);
- if (list == NULL) {
- list = PyList_New(0);
- if (list == NULL)
- return -1;
- if (PyDict_SetItemString(dict, KEY, list) < 0)
- return -1;
- Py_DECREF(list);
- }
- i = PyList_GET_SIZE(list);
- while (--i >= 0) {
- if (PyList_GET_ITEM(list, i) == obj)
- return 1;
- }
- PyList_Append(list, obj);
- return 0;
-}
-
-void
-Py_ReprLeave(PyObject *obj)
-{
- PyObject *dict;
- PyObject *list;
- Py_ssize_t i;
-
- dict = PyThreadState_GetDict();
- if (dict == NULL)
- return;
- list = PyDict_GetItemString(dict, KEY);
- if (list == NULL || !PyList_Check(list))
- return;
- i = PyList_GET_SIZE(list);
- /* Count backwards because we always expect obj to be list[-1] */
- while (--i >= 0) {
- if (PyList_GET_ITEM(list, i) == obj) {
- PyList_SetSlice(list, i, i + 1, NULL);
- break;
- }
- }
-}
-
-/* Trashcan support. */
-
-/* Current call-stack depth of tp_dealloc calls. */
-int _PyTrash_delete_nesting = 0;
-
-/* List of objects that still need to be cleaned up, singly linked via their
- * gc headers' gc_prev pointers.
- */
-PyObject *_PyTrash_delete_later = NULL;
-
-/* Add op to the _PyTrash_delete_later list. Called when the current
- * call-stack depth gets large. op must be a currently untracked gc'ed
- * object, with refcount 0. Py_DECREF must already have been called on it.
- */
-void
-_PyTrash_deposit_object(PyObject *op)
-{
- assert(PyObject_IS_GC(op));
- assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED);
- assert(op->ob_refcnt == 0);
- _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *)_PyTrash_delete_later;
- _PyTrash_delete_later = op;
-}
-
-/* Dealloccate all the objects in the _PyTrash_delete_later list. Called when
- * the call-stack unwinds again.
- */
-void
-_PyTrash_destroy_chain(void)
-{
- while (_PyTrash_delete_later) {
- PyObject *op = _PyTrash_delete_later;
- destructor dealloc = op->ob_type->tp_dealloc;
-
- _PyTrash_delete_later =
- (PyObject*) _Py_AS_GC(op)->gc.gc_prev;
-
- /* Call the deallocator directly. This used to try to
- * fool Py_DECREF into calling it indirectly, but
- * Py_DECREF was already called on this object, and in
- * assorted non-release builds calling Py_DECREF again ends
- * up distorting allocation statistics.
- */
- assert(op->ob_refcnt == 0);
- ++_PyTrash_delete_nesting;
- (*dealloc)(op);
- --_PyTrash_delete_nesting;
- }
-}
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/sys/src/cmd/python/Objects/obmalloc.c b/sys/src/cmd/python/Objects/obmalloc.c
deleted file mode 100644
index 840570e06..000000000
--- a/sys/src/cmd/python/Objects/obmalloc.c
+++ /dev/null
@@ -1,1745 +0,0 @@
-#include "Python.h"
-
-#ifdef WITH_PYMALLOC
-
-/* An object allocator for Python.
-
- Here is an introduction to the layers of the Python memory architecture,
- showing where the object allocator is actually used (layer +2), It is
- called for every object allocation and deallocation (PyObject_New/Del),
- unless the object-specific allocators implement a proprietary allocation
- scheme (ex.: ints use a simple free list). This is also the place where
- the cyclic garbage collector operates selectively on container objects.
-
-
- Object-specific allocators
- _____ ______ ______ ________
- [ int ] [ dict ] [ list ] ... [ string ] Python core |
-+3 | <----- Object-specific memory -----> | <-- Non-object memory --> |
- _______________________________ | |
- [ Python's object allocator ] | |
-+2 | ####### Object memory ####### | <------ Internal buffers ------> |
- ______________________________________________________________ |
- [ Python's raw memory allocator (PyMem_ API) ] |
-+1 | <----- Python memory (under PyMem manager's control) ------> | |
- __________________________________________________________________
- [ Underlying general-purpose allocator (ex: C library malloc) ]
- 0 | <------ Virtual memory allocated for the python process -------> |
-
- =========================================================================
- _______________________________________________________________________
- [ OS-specific Virtual Memory Manager (VMM) ]
--1 | <--- Kernel dynamic storage allocation & management (page-based) ---> |
- __________________________________ __________________________________
- [ ] [ ]
--2 | <-- Physical memory: ROM/RAM --> | | <-- Secondary storage (swap) --> |
-
-*/
-/*==========================================================================*/
-
-/* A fast, special-purpose memory allocator for small blocks, to be used
- on top of a general-purpose malloc -- heavily based on previous art. */
-
-/* Vladimir Marangozov -- August 2000 */
-
-/*
- * "Memory management is where the rubber meets the road -- if we do the wrong
- * thing at any level, the results will not be good. And if we don't make the
- * levels work well together, we are in serious trouble." (1)
- *
- * (1) Paul R. Wilson, Mark S. Johnstone, Michael Neely, and David Boles,
- * "Dynamic Storage Allocation: A Survey and Critical Review",
- * in Proc. 1995 Int'l. Workshop on Memory Management, September 1995.
- */
-
-/* #undef WITH_MEMORY_LIMITS */ /* disable mem limit checks */
-
-/*==========================================================================*/
-
-/*
- * Allocation strategy abstract:
- *
- * For small requests, the allocator sub-allocates <Big> blocks of memory.
- * Requests greater than 256 bytes are routed to the system's allocator.
- *
- * Small requests are grouped in size classes spaced 8 bytes apart, due
- * to the required valid alignment of the returned address. Requests of
- * a particular size are serviced from memory pools of 4K (one VMM page).
- * Pools are fragmented on demand and contain free lists of blocks of one
- * particular size class. In other words, there is a fixed-size allocator
- * for each size class. Free pools are shared by the different allocators
- * thus minimizing the space reserved for a particular size class.
- *
- * This allocation strategy is a variant of what is known as "simple
- * segregated storage based on array of free lists". The main drawback of
- * simple segregated storage is that we might end up with lot of reserved
- * memory for the different free lists, which degenerate in time. To avoid
- * this, we partition each free list in pools and we share dynamically the
- * reserved space between all free lists. This technique is quite efficient
- * for memory intensive programs which allocate mainly small-sized blocks.
- *
- * For small requests we have the following table:
- *
- * Request in bytes Size of allocated block Size class idx
- * ----------------------------------------------------------------
- * 1-8 8 0
- * 9-16 16 1
- * 17-24 24 2
- * 25-32 32 3
- * 33-40 40 4
- * 41-48 48 5
- * 49-56 56 6
- * 57-64 64 7
- * 65-72 72 8
- * ... ... ...
- * 241-248 248 30
- * 249-256 256 31
- *
- * 0, 257 and up: routed to the underlying allocator.
- */
-
-/*==========================================================================*/
-
-/*
- * -- Main tunable settings section --
- */
-
-/*
- * Alignment of addresses returned to the user. 8-bytes alignment works
- * on most current architectures (with 32-bit or 64-bit address busses).
- * The alignment value is also used for grouping small requests in size
- * classes spaced ALIGNMENT bytes apart.
- *
- * You shouldn't change this unless you know what you are doing.
- */
-#define ALIGNMENT 8 /* must be 2^N */
-#define ALIGNMENT_SHIFT 3
-#define ALIGNMENT_MASK (ALIGNMENT - 1)
-
-/* Return the number of bytes in size class I, as a uint. */
-#define INDEX2SIZE(I) (((uint)(I) + 1) << ALIGNMENT_SHIFT)
-
-/*
- * Max size threshold below which malloc requests are considered to be
- * small enough in order to use preallocated memory pools. You can tune
- * this value according to your application behaviour and memory needs.
- *
- * The following invariants must hold:
- * 1) ALIGNMENT <= SMALL_REQUEST_THRESHOLD <= 256
- * 2) SMALL_REQUEST_THRESHOLD is evenly divisible by ALIGNMENT
- *
- * Although not required, for better performance and space efficiency,
- * it is recommended that SMALL_REQUEST_THRESHOLD is set to a power of 2.
- */
-#define SMALL_REQUEST_THRESHOLD 256
-#define NB_SMALL_SIZE_CLASSES (SMALL_REQUEST_THRESHOLD / ALIGNMENT)
-
-/*
- * The system's VMM page size can be obtained on most unices with a
- * getpagesize() call or deduced from various header files. To make
- * things simpler, we assume that it is 4K, which is OK for most systems.
- * It is probably better if this is the native page size, but it doesn't
- * have to be. In theory, if SYSTEM_PAGE_SIZE is larger than the native page
- * size, then `POOL_ADDR(p)->arenaindex' could rarely cause a segmentation
- * violation fault. 4K is apparently OK for all the platforms that python
- * currently targets.
- */
-#define SYSTEM_PAGE_SIZE (4 * 1024)
-#define SYSTEM_PAGE_SIZE_MASK (SYSTEM_PAGE_SIZE - 1)
-
-/*
- * Maximum amount of memory managed by the allocator for small requests.
- */
-#ifdef WITH_MEMORY_LIMITS
-#ifndef SMALL_MEMORY_LIMIT
-#define SMALL_MEMORY_LIMIT (64 * 1024 * 1024) /* 64 MB -- more? */
-#endif
-#endif
-
-/*
- * The allocator sub-allocates <Big> blocks of memory (called arenas) aligned
- * on a page boundary. This is a reserved virtual address space for the
- * current process (obtained through a malloc call). In no way this means
- * that the memory arenas will be used entirely. A malloc(<Big>) is usually
- * an address range reservation for <Big> bytes, unless all pages within this
- * space are referenced subsequently. So malloc'ing big blocks and not using
- * them does not mean "wasting memory". It's an addressable range wastage...
- *
- * Therefore, allocating arenas with malloc is not optimal, because there is
- * some address space wastage, but this is the most portable way to request
- * memory from the system across various platforms.
- */
-#define ARENA_SIZE (256 << 10) /* 256KB */
-
-#ifdef WITH_MEMORY_LIMITS
-#define MAX_ARENAS (SMALL_MEMORY_LIMIT / ARENA_SIZE)
-#endif
-
-/*
- * Size of the pools used for small blocks. Should be a power of 2,
- * between 1K and SYSTEM_PAGE_SIZE, that is: 1k, 2k, 4k.
- */
-#define POOL_SIZE SYSTEM_PAGE_SIZE /* must be 2^N */
-#define POOL_SIZE_MASK SYSTEM_PAGE_SIZE_MASK
-
-/*
- * -- End of tunable settings section --
- */
-
-/*==========================================================================*/
-
-/*
- * Locking
- *
- * To reduce lock contention, it would probably be better to refine the
- * crude function locking with per size class locking. I'm not positive
- * however, whether it's worth switching to such locking policy because
- * of the performance penalty it might introduce.
- *
- * The following macros describe the simplest (should also be the fastest)
- * lock object on a particular platform and the init/fini/lock/unlock
- * operations on it. The locks defined here are not expected to be recursive
- * because it is assumed that they will always be called in the order:
- * INIT, [LOCK, UNLOCK]*, FINI.
- */
-
-/*
- * Python's threads are serialized, so object malloc locking is disabled.
- */
-#define SIMPLELOCK_DECL(lock) /* simple lock declaration */
-#define SIMPLELOCK_INIT(lock) /* allocate (if needed) and initialize */
-#define SIMPLELOCK_FINI(lock) /* free/destroy an existing lock */
-#define SIMPLELOCK_LOCK(lock) /* acquire released lock */
-#define SIMPLELOCK_UNLOCK(lock) /* release acquired lock */
-
-/*
- * Basic types
- * I don't care if these are defined in <sys/types.h> or elsewhere. Axiom.
- */
-#undef uchar
-#define uchar unsigned char /* assuming == 8 bits */
-
-#undef uint
-#define uint unsigned int /* assuming >= 16 bits */
-
-#undef ulong
-#define ulong unsigned long /* assuming >= 32 bits */
-
-#undef uptr
-#define uptr Py_uintptr_t
-
-/* When you say memory, my mind reasons in terms of (pointers to) blocks */
-typedef uchar block;
-
-/* Pool for small blocks. */
-struct pool_header {
- union { block *_padding;
- uint count; } ref; /* number of allocated blocks */
- block *freeblock; /* pool's free list head */
- struct pool_header *nextpool; /* next pool of this size class */
- struct pool_header *prevpool; /* previous pool "" */
- uint arenaindex; /* index into arenas of base adr */
- uint szidx; /* block size class index */
- uint nextoffset; /* bytes to virgin block */
- uint maxnextoffset; /* largest valid nextoffset */
-};
-
-typedef struct pool_header *poolp;
-
-/* Record keeping for arenas. */
-struct arena_object {
- /* The address of the arena, as returned by malloc. Note that 0
- * will never be returned by a successful malloc, and is used
- * here to mark an arena_object that doesn't correspond to an
- * allocated arena.
- */
- uptr address;
-
- /* Pool-aligned pointer to the next pool to be carved off. */
- block* pool_address;
-
- /* The number of available pools in the arena: free pools + never-
- * allocated pools.
- */
- uint nfreepools;
-
- /* The total number of pools in the arena, whether or not available. */
- uint ntotalpools;
-
- /* Singly-linked list of available pools. */
- struct pool_header* freepools;
-
- /* Whenever this arena_object is not associated with an allocated
- * arena, the nextarena member is used to link all unassociated
- * arena_objects in the singly-linked `unused_arena_objects` list.
- * The prevarena member is unused in this case.
- *
- * When this arena_object is associated with an allocated arena
- * with at least one available pool, both members are used in the
- * doubly-linked `usable_arenas` list, which is maintained in
- * increasing order of `nfreepools` values.
- *
- * Else this arena_object is associated with an allocated arena
- * all of whose pools are in use. `nextarena` and `prevarena`
- * are both meaningless in this case.
- */
- struct arena_object* nextarena;
- struct arena_object* prevarena;
-};
-
-#undef ROUNDUP
-#define ROUNDUP(x) (((x) + ALIGNMENT_MASK) & ~ALIGNMENT_MASK)
-#define POOL_OVERHEAD ROUNDUP(sizeof(struct pool_header))
-
-#define DUMMY_SIZE_IDX 0xffff /* size class of newly cached pools */
-
-/* Round pointer P down to the closest pool-aligned address <= P, as a poolp */
-#define POOL_ADDR(P) ((poolp)((uptr)(P) & ~(uptr)POOL_SIZE_MASK))
-
-/* Return total number of blocks in pool of size index I, as a uint. */
-#define NUMBLOCKS(I) ((uint)(POOL_SIZE - POOL_OVERHEAD) / INDEX2SIZE(I))
-
-/*==========================================================================*/
-
-/*
- * This malloc lock
- */
-SIMPLELOCK_DECL(_malloc_lock)
-#define LOCK() SIMPLELOCK_LOCK(_malloc_lock)
-#define UNLOCK() SIMPLELOCK_UNLOCK(_malloc_lock)
-#define LOCK_INIT() SIMPLELOCK_INIT(_malloc_lock)
-#define LOCK_FINI() SIMPLELOCK_FINI(_malloc_lock)
-
-/*
- * Pool table -- headed, circular, doubly-linked lists of partially used pools.
-
-This is involved. For an index i, usedpools[i+i] is the header for a list of
-all partially used pools holding small blocks with "size class idx" i. So
-usedpools[0] corresponds to blocks of size 8, usedpools[2] to blocks of size
-16, and so on: index 2*i <-> blocks of size (i+1)<<ALIGNMENT_SHIFT.
-
-Pools are carved off an arena's highwater mark (an arena_object's pool_address
-member) as needed. Once carved off, a pool is in one of three states forever
-after:
-
-used == partially used, neither empty nor full
- At least one block in the pool is currently allocated, and at least one
- block in the pool is not currently allocated (note this implies a pool
- has room for at least two blocks).
- This is a pool's initial state, as a pool is created only when malloc
- needs space.
- The pool holds blocks of a fixed size, and is in the circular list headed
- at usedpools[i] (see above). It's linked to the other used pools of the
- same size class via the pool_header's nextpool and prevpool members.
- If all but one block is currently allocated, a malloc can cause a
- transition to the full state. If all but one block is not currently
- allocated, a free can cause a transition to the empty state.
-
-full == all the pool's blocks are currently allocated
- On transition to full, a pool is unlinked from its usedpools[] list.
- It's not linked to from anything then anymore, and its nextpool and
- prevpool members are meaningless until it transitions back to used.
- A free of a block in a full pool puts the pool back in the used state.
- Then it's linked in at the front of the appropriate usedpools[] list, so
- that the next allocation for its size class will reuse the freed block.
-
-empty == all the pool's blocks are currently available for allocation
- On transition to empty, a pool is unlinked from its usedpools[] list,
- and linked to the front of its arena_object's singly-linked freepools list,
- via its nextpool member. The prevpool member has no meaning in this case.
- Empty pools have no inherent size class: the next time a malloc finds
- an empty list in usedpools[], it takes the first pool off of freepools.
- If the size class needed happens to be the same as the size class the pool
- last had, some pool initialization can be skipped.
-
-
-Block Management
-
-Blocks within pools are again carved out as needed. pool->freeblock points to
-the start of a singly-linked list of free blocks within the pool. When a
-block is freed, it's inserted at the front of its pool's freeblock list. Note
-that the available blocks in a pool are *not* linked all together when a pool
-is initialized. Instead only "the first two" (lowest addresses) blocks are
-set up, returning the first such block, and setting pool->freeblock to a
-one-block list holding the second such block. This is consistent with that
-pymalloc strives at all levels (arena, pool, and block) never to touch a piece
-of memory until it's actually needed.
-
-So long as a pool is in the used state, we're certain there *is* a block
-available for allocating, and pool->freeblock is not NULL. If pool->freeblock
-points to the end of the free list before we've carved the entire pool into
-blocks, that means we simply haven't yet gotten to one of the higher-address
-blocks. The offset from the pool_header to the start of "the next" virgin
-block is stored in the pool_header nextoffset member, and the largest value
-of nextoffset that makes sense is stored in the maxnextoffset member when a
-pool is initialized. All the blocks in a pool have been passed out at least
-once when and only when nextoffset > maxnextoffset.
-
-
-Major obscurity: While the usedpools vector is declared to have poolp
-entries, it doesn't really. It really contains two pointers per (conceptual)
-poolp entry, the nextpool and prevpool members of a pool_header. The
-excruciating initialization code below fools C so that
-
- usedpool[i+i]
-
-"acts like" a genuine poolp, but only so long as you only reference its
-nextpool and prevpool members. The "- 2*sizeof(block *)" gibberish is
-compensating for that a pool_header's nextpool and prevpool members
-immediately follow a pool_header's first two members:
-
- union { block *_padding;
- uint count; } ref;
- block *freeblock;
-
-each of which consume sizeof(block *) bytes. So what usedpools[i+i] really
-contains is a fudged-up pointer p such that *if* C believes it's a poolp
-pointer, then p->nextpool and p->prevpool are both p (meaning that the headed
-circular list is empty).
-
-It's unclear why the usedpools setup is so convoluted. It could be to
-minimize the amount of cache required to hold this heavily-referenced table
-(which only *needs* the two interpool pointer members of a pool_header). OTOH,
-referencing code has to remember to "double the index" and doing so isn't
-free, usedpools[0] isn't a strictly legal pointer, and we're crucially relying
-on that C doesn't insert any padding anywhere in a pool_header at or before
-the prevpool member.
-**************************************************************************** */
-
-#define PTA(x) ((poolp )((uchar *)&(usedpools[2*(x)]) - 2*sizeof(block *)))
-#define PT(x) PTA(x), PTA(x)
-
-static poolp usedpools[2 * ((NB_SMALL_SIZE_CLASSES + 7) / 8) * 8] = {
- PT(0), PT(1), PT(2), PT(3), PT(4), PT(5), PT(6), PT(7)
-#if NB_SMALL_SIZE_CLASSES > 8
- , PT(8), PT(9), PT(10), PT(11), PT(12), PT(13), PT(14), PT(15)
-#if NB_SMALL_SIZE_CLASSES > 16
- , PT(16), PT(17), PT(18), PT(19), PT(20), PT(21), PT(22), PT(23)
-#if NB_SMALL_SIZE_CLASSES > 24
- , PT(24), PT(25), PT(26), PT(27), PT(28), PT(29), PT(30), PT(31)
-#if NB_SMALL_SIZE_CLASSES > 32
- , PT(32), PT(33), PT(34), PT(35), PT(36), PT(37), PT(38), PT(39)
-#if NB_SMALL_SIZE_CLASSES > 40
- , PT(40), PT(41), PT(42), PT(43), PT(44), PT(45), PT(46), PT(47)
-#if NB_SMALL_SIZE_CLASSES > 48
- , PT(48), PT(49), PT(50), PT(51), PT(52), PT(53), PT(54), PT(55)
-#if NB_SMALL_SIZE_CLASSES > 56
- , PT(56), PT(57), PT(58), PT(59), PT(60), PT(61), PT(62), PT(63)
-#endif /* NB_SMALL_SIZE_CLASSES > 56 */
-#endif /* NB_SMALL_SIZE_CLASSES > 48 */
-#endif /* NB_SMALL_SIZE_CLASSES > 40 */
-#endif /* NB_SMALL_SIZE_CLASSES > 32 */
-#endif /* NB_SMALL_SIZE_CLASSES > 24 */
-#endif /* NB_SMALL_SIZE_CLASSES > 16 */
-#endif /* NB_SMALL_SIZE_CLASSES > 8 */
-};
-
-/*==========================================================================
-Arena management.
-
-`arenas` is a vector of arena_objects. It contains maxarenas entries, some of
-which may not be currently used (== they're arena_objects that aren't
-currently associated with an allocated arena). Note that arenas proper are
-separately malloc'ed.
-
-Prior to Python 2.5, arenas were never free()'ed. Starting with Python 2.5,
-we do try to free() arenas, and use some mild heuristic strategies to increase
-the likelihood that arenas eventually can be freed.
-
-unused_arena_objects
-
- This is a singly-linked list of the arena_objects that are currently not
- being used (no arena is associated with them). Objects are taken off the
- head of the list in new_arena(), and are pushed on the head of the list in
- PyObject_Free() when the arena is empty. Key invariant: an arena_object
- is on this list if and only if its .address member is 0.
-
-usable_arenas
-
- This is a doubly-linked list of the arena_objects associated with arenas
- that have pools available. These pools are either waiting to be reused,
- or have not been used before. The list is sorted to have the most-
- allocated arenas first (ascending order based on the nfreepools member).
- This means that the next allocation will come from a heavily used arena,
- which gives the nearly empty arenas a chance to be returned to the system.
- In my unscientific tests this dramatically improved the number of arenas
- that could be freed.
-
-Note that an arena_object associated with an arena all of whose pools are
-currently in use isn't on either list.
-*/
-
-/* Array of objects used to track chunks of memory (arenas). */
-static struct arena_object* arenas = NULL;
-/* Number of slots currently allocated in the `arenas` vector. */
-static uint maxarenas = 0;
-
-/* The head of the singly-linked, NULL-terminated list of available
- * arena_objects.
- */
-static struct arena_object* unused_arena_objects = NULL;
-
-/* The head of the doubly-linked, NULL-terminated at each end, list of
- * arena_objects associated with arenas that have pools available.
- */
-static struct arena_object* usable_arenas = NULL;
-
-/* How many arena_objects do we initially allocate?
- * 16 = can allocate 16 arenas = 16 * ARENA_SIZE = 4MB before growing the
- * `arenas` vector.
- */
-#define INITIAL_ARENA_OBJECTS 16
-
-/* Number of arenas allocated that haven't been free()'d. */
-static size_t narenas_currently_allocated = 0;
-
-#ifdef PYMALLOC_DEBUG
-/* Total number of times malloc() called to allocate an arena. */
-static size_t ntimes_arena_allocated = 0;
-/* High water mark (max value ever seen) for narenas_currently_allocated. */
-static size_t narenas_highwater = 0;
-#endif
-
-/* Allocate a new arena. If we run out of memory, return NULL. Else
- * allocate a new arena, and return the address of an arena_object
- * describing the new arena. It's expected that the caller will set
- * `usable_arenas` to the return value.
- */
-static struct arena_object*
-new_arena(void)
-{
- struct arena_object* arenaobj;
- uint excess; /* number of bytes above pool alignment */
-
-#ifdef PYMALLOC_DEBUG
- if (Py_GETENV("PYTHONMALLOCSTATS"))
- _PyObject_DebugMallocStats();
-#endif
- if (unused_arena_objects == NULL) {
- uint i;
- uint numarenas;
- size_t nbytes;
-
- /* Double the number of arena objects on each allocation.
- * Note that it's possible for `numarenas` to overflow.
- */
- numarenas = maxarenas ? maxarenas << 1 : INITIAL_ARENA_OBJECTS;
- if (numarenas <= maxarenas)
- return NULL; /* overflow */
- nbytes = numarenas * sizeof(*arenas);
- if (nbytes / sizeof(*arenas) != numarenas)
- return NULL; /* overflow */
- arenaobj = (struct arena_object *)realloc(arenas, nbytes);
- if (arenaobj == NULL)
- return NULL;
- arenas = arenaobj;
-
- /* We might need to fix pointers that were copied. However,
- * new_arena only gets called when all the pages in the
- * previous arenas are full. Thus, there are *no* pointers
- * into the old array. Thus, we don't have to worry about
- * invalid pointers. Just to be sure, some asserts:
- */
- assert(usable_arenas == NULL);
- assert(unused_arena_objects == NULL);
-
- /* Put the new arenas on the unused_arena_objects list. */
- for (i = maxarenas; i < numarenas; ++i) {
- arenas[i].address = 0; /* mark as unassociated */
- arenas[i].nextarena = i < numarenas - 1 ?
- &arenas[i+1] : NULL;
- }
-
- /* Update globals. */
- unused_arena_objects = &arenas[maxarenas];
- maxarenas = numarenas;
- }
-
- /* Take the next available arena object off the head of the list. */
- assert(unused_arena_objects != NULL);
- arenaobj = unused_arena_objects;
- unused_arena_objects = arenaobj->nextarena;
- assert(arenaobj->address == 0);
- arenaobj->address = (uptr)malloc(ARENA_SIZE);
- if (arenaobj->address == 0) {
- /* The allocation failed: return NULL after putting the
- * arenaobj back.
- */
- arenaobj->nextarena = unused_arena_objects;
- unused_arena_objects = arenaobj;
- return NULL;
- }
-
- ++narenas_currently_allocated;
-#ifdef PYMALLOC_DEBUG
- ++ntimes_arena_allocated;
- if (narenas_currently_allocated > narenas_highwater)
- narenas_highwater = narenas_currently_allocated;
-#endif
- arenaobj->freepools = NULL;
- /* pool_address <- first pool-aligned address in the arena
- nfreepools <- number of whole pools that fit after alignment */
- arenaobj->pool_address = (block*)arenaobj->address;
- arenaobj->nfreepools = ARENA_SIZE / POOL_SIZE;
- assert(POOL_SIZE * arenaobj->nfreepools == ARENA_SIZE);
- excess = (uint)(arenaobj->address & POOL_SIZE_MASK);
- if (excess != 0) {
- --arenaobj->nfreepools;
- arenaobj->pool_address += POOL_SIZE - excess;
- }
- arenaobj->ntotalpools = arenaobj->nfreepools;
-
- return arenaobj;
-}
-
-/*
-Py_ADDRESS_IN_RANGE(P, POOL)
-
-Return true if and only if P is an address that was allocated by pymalloc.
-POOL must be the pool address associated with P, i.e., POOL = POOL_ADDR(P)
-(the caller is asked to compute this because the macro expands POOL more than
-once, and for efficiency it's best for the caller to assign POOL_ADDR(P) to a
-variable and pass the latter to the macro; because Py_ADDRESS_IN_RANGE is
-called on every alloc/realloc/free, micro-efficiency is important here).
-
-Tricky: Let B be the arena base address associated with the pool, B =
-arenas[(POOL)->arenaindex].address. Then P belongs to the arena if and only if
-
- B <= P < B + ARENA_SIZE
-
-Subtracting B throughout, this is true iff
-
- 0 <= P-B < ARENA_SIZE
-
-By using unsigned arithmetic, the "0 <=" half of the test can be skipped.
-
-Obscure: A PyMem "free memory" function can call the pymalloc free or realloc
-before the first arena has been allocated. `arenas` is still NULL in that
-case. We're relying on that maxarenas is also 0 in that case, so that
-(POOL)->arenaindex < maxarenas must be false, saving us from trying to index
-into a NULL arenas.
-
-Details: given P and POOL, the arena_object corresponding to P is AO =
-arenas[(POOL)->arenaindex]. Suppose obmalloc controls P. Then (barring wild
-stores, etc), POOL is the correct address of P's pool, AO.address is the
-correct base address of the pool's arena, and P must be within ARENA_SIZE of
-AO.address. In addition, AO.address is not 0 (no arena can start at address 0
-(NULL)). Therefore Py_ADDRESS_IN_RANGE correctly reports that obmalloc
-controls P.
-
-Now suppose obmalloc does not control P (e.g., P was obtained via a direct
-call to the system malloc() or realloc()). (POOL)->arenaindex may be anything
-in this case -- it may even be uninitialized trash. If the trash arenaindex
-is >= maxarenas, the macro correctly concludes at once that obmalloc doesn't
-control P.
-
-Else arenaindex is < maxarena, and AO is read up. If AO corresponds to an
-allocated arena, obmalloc controls all the memory in slice AO.address :
-AO.address+ARENA_SIZE. By case assumption, P is not controlled by obmalloc,
-so P doesn't lie in that slice, so the macro correctly reports that P is not
-controlled by obmalloc.
-
-Finally, if P is not controlled by obmalloc and AO corresponds to an unused
-arena_object (one not currently associated with an allocated arena),
-AO.address is 0, and the second test in the macro reduces to:
-
- P < ARENA_SIZE
-
-If P >= ARENA_SIZE (extremely likely), the macro again correctly concludes
-that P is not controlled by obmalloc. However, if P < ARENA_SIZE, this part
-of the test still passes, and the third clause (AO.address != 0) is necessary
-to get the correct result: AO.address is 0 in this case, so the macro
-correctly reports that P is not controlled by obmalloc (despite that P lies in
-slice AO.address : AO.address + ARENA_SIZE).
-
-Note: The third (AO.address != 0) clause was added in Python 2.5. Before
-2.5, arenas were never free()'ed, and an arenaindex < maxarena always
-corresponded to a currently-allocated arena, so the "P is not controlled by
-obmalloc, AO corresponds to an unused arena_object, and P < ARENA_SIZE" case
-was impossible.
-
-Note that the logic is excruciating, and reading up possibly uninitialized
-memory when P is not controlled by obmalloc (to get at (POOL)->arenaindex)
-creates problems for some memory debuggers. The overwhelming advantage is
-that this test determines whether an arbitrary address is controlled by
-obmalloc in a small constant time, independent of the number of arenas
-obmalloc controls. Since this test is needed at every entry point, it's
-extremely desirable that it be this fast.
-*/
-#define Py_ADDRESS_IN_RANGE(P, POOL) \
- ((POOL)->arenaindex < maxarenas && \
- (uptr)(P) - arenas[(POOL)->arenaindex].address < (uptr)ARENA_SIZE && \
- arenas[(POOL)->arenaindex].address != 0)
-
-
-/* This is only useful when running memory debuggers such as
- * Purify or Valgrind. Uncomment to use.
- *
-#define Py_USING_MEMORY_DEBUGGER
- */
-
-#ifdef Py_USING_MEMORY_DEBUGGER
-
-/* Py_ADDRESS_IN_RANGE may access uninitialized memory by design
- * This leads to thousands of spurious warnings when using
- * Purify or Valgrind. By making a function, we can easily
- * suppress the uninitialized memory reads in this one function.
- * So we won't ignore real errors elsewhere.
- *
- * Disable the macro and use a function.
- */
-
-#undef Py_ADDRESS_IN_RANGE
-
-#if defined(__GNUC__) && ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1) || \
- (__GNUC__ >= 4))
-#define Py_NO_INLINE __attribute__((__noinline__))
-#else
-#define Py_NO_INLINE
-#endif
-
-/* Don't make static, to try to ensure this isn't inlined. */
-int Py_ADDRESS_IN_RANGE(void *P, poolp pool) Py_NO_INLINE;
-#undef Py_NO_INLINE
-#endif
-
-/*==========================================================================*/
-
-/* malloc. Note that nbytes==0 tries to return a non-NULL pointer, distinct
- * from all other currently live pointers. This may not be possible.
- */
-
-/*
- * The basic blocks are ordered by decreasing execution frequency,
- * which minimizes the number of jumps in the most common cases,
- * improves branching prediction and instruction scheduling (small
- * block allocations typically result in a couple of instructions).
- * Unless the optimizer reorders everything, being too smart...
- */
-
-#undef PyObject_Malloc
-void *
-PyObject_Malloc(size_t nbytes)
-{
- block *bp;
- poolp pool;
- poolp next;
- uint size;
-
- /*
- * This implicitly redirects malloc(0).
- */
- if ((nbytes - 1) < SMALL_REQUEST_THRESHOLD) {
- LOCK();
- /*
- * Most frequent paths first
- */
- size = (uint)(nbytes - 1) >> ALIGNMENT_SHIFT;
- pool = usedpools[size + size];
- if (pool != pool->nextpool) {
- /*
- * There is a used pool for this size class.
- * Pick up the head block of its free list.
- */
- ++pool->ref.count;
- bp = pool->freeblock;
- assert(bp != NULL);
- if ((pool->freeblock = *(block **)bp) != NULL) {
- UNLOCK();
- return (void *)bp;
- }
- /*
- * Reached the end of the free list, try to extend it.
- */
- if (pool->nextoffset <= pool->maxnextoffset) {
- /* There is room for another block. */
- pool->freeblock = (block*)pool +
- pool->nextoffset;
- pool->nextoffset += INDEX2SIZE(size);
- *(block **)(pool->freeblock) = NULL;
- UNLOCK();
- return (void *)bp;
- }
- /* Pool is full, unlink from used pools. */
- next = pool->nextpool;
- pool = pool->prevpool;
- next->prevpool = pool;
- pool->nextpool = next;
- UNLOCK();
- return (void *)bp;
- }
-
- /* There isn't a pool of the right size class immediately
- * available: use a free pool.
- */
- if (usable_arenas == NULL) {
- /* No arena has a free pool: allocate a new arena. */
-#ifdef WITH_MEMORY_LIMITS
- if (narenas_currently_allocated >= MAX_ARENAS) {
- UNLOCK();
- goto redirect;
- }
-#endif
- usable_arenas = new_arena();
- if (usable_arenas == NULL) {
- UNLOCK();
- goto redirect;
- }
- usable_arenas->nextarena =
- usable_arenas->prevarena = NULL;
- }
- assert(usable_arenas->address != 0);
-
- /* Try to get a cached free pool. */
- pool = usable_arenas->freepools;
- if (pool != NULL) {
- /* Unlink from cached pools. */
- usable_arenas->freepools = pool->nextpool;
-
- /* This arena already had the smallest nfreepools
- * value, so decreasing nfreepools doesn't change
- * that, and we don't need to rearrange the
- * usable_arenas list. However, if the arena has
- * become wholly allocated, we need to remove its
- * arena_object from usable_arenas.
- */
- --usable_arenas->nfreepools;
- if (usable_arenas->nfreepools == 0) {
- /* Wholly allocated: remove. */
- assert(usable_arenas->freepools == NULL);
- assert(usable_arenas->nextarena == NULL ||
- usable_arenas->nextarena->prevarena ==
- usable_arenas);
-
- usable_arenas = usable_arenas->nextarena;
- if (usable_arenas != NULL) {
- usable_arenas->prevarena = NULL;
- assert(usable_arenas->address != 0);
- }
- }
- else {
- /* nfreepools > 0: it must be that freepools
- * isn't NULL, or that we haven't yet carved
- * off all the arena's pools for the first
- * time.
- */
- assert(usable_arenas->freepools != NULL ||
- usable_arenas->pool_address <=
- (block*)usable_arenas->address +
- ARENA_SIZE - POOL_SIZE);
- }
- init_pool:
- /* Frontlink to used pools. */
- next = usedpools[size + size]; /* == prev */
- pool->nextpool = next;
- pool->prevpool = next;
- next->nextpool = pool;
- next->prevpool = pool;
- pool->ref.count = 1;
- if (pool->szidx == size) {
- /* Luckily, this pool last contained blocks
- * of the same size class, so its header
- * and free list are already initialized.
- */
- bp = pool->freeblock;
- pool->freeblock = *(block **)bp;
- UNLOCK();
- return (void *)bp;
- }
- /*
- * Initialize the pool header, set up the free list to
- * contain just the second block, and return the first
- * block.
- */
- pool->szidx = size;
- size = INDEX2SIZE(size);
- bp = (block *)pool + POOL_OVERHEAD;
- pool->nextoffset = POOL_OVERHEAD + (size << 1);
- pool->maxnextoffset = POOL_SIZE - size;
- pool->freeblock = bp + size;
- *(block **)(pool->freeblock) = NULL;
- UNLOCK();
- return (void *)bp;
- }
-
- /* Carve off a new pool. */
- assert(usable_arenas->nfreepools > 0);
- assert(usable_arenas->freepools == NULL);
- pool = (poolp)usable_arenas->pool_address;
- assert((block*)pool <= (block*)usable_arenas->address +
- ARENA_SIZE - POOL_SIZE);
- pool->arenaindex = usable_arenas - arenas;
- assert(&arenas[pool->arenaindex] == usable_arenas);
- pool->szidx = DUMMY_SIZE_IDX;
- usable_arenas->pool_address += POOL_SIZE;
- --usable_arenas->nfreepools;
-
- if (usable_arenas->nfreepools == 0) {
- assert(usable_arenas->nextarena == NULL ||
- usable_arenas->nextarena->prevarena ==
- usable_arenas);
- /* Unlink the arena: it is completely allocated. */
- usable_arenas = usable_arenas->nextarena;
- if (usable_arenas != NULL) {
- usable_arenas->prevarena = NULL;
- assert(usable_arenas->address != 0);
- }
- }
-
- goto init_pool;
- }
-
- /* The small block allocator ends here. */
-
-redirect:
- /* Redirect the original request to the underlying (libc) allocator.
- * We jump here on bigger requests, on error in the code above (as a
- * last chance to serve the request) or when the max memory limit
- * has been reached.
- */
- if (nbytes == 0)
- nbytes = 1;
- return (void *)malloc(nbytes);
-}
-
-/* free */
-
-#undef PyObject_Free
-void
-PyObject_Free(void *p)
-{
- poolp pool;
- block *lastfree;
- poolp next, prev;
- uint size;
-
- if (p == NULL) /* free(NULL) has no effect */
- return;
-
- pool = POOL_ADDR(p);
- if (Py_ADDRESS_IN_RANGE(p, pool)) {
- /* We allocated this address. */
- LOCK();
- /* Link p to the start of the pool's freeblock list. Since
- * the pool had at least the p block outstanding, the pool
- * wasn't empty (so it's already in a usedpools[] list, or
- * was full and is in no list -- it's not in the freeblocks
- * list in any case).
- */
- assert(pool->ref.count > 0); /* else it was empty */
- *(block **)p = lastfree = pool->freeblock;
- pool->freeblock = (block *)p;
- if (lastfree) {
- struct arena_object* ao;
- uint nf; /* ao->nfreepools */
-
- /* freeblock wasn't NULL, so the pool wasn't full,
- * and the pool is in a usedpools[] list.
- */
- if (--pool->ref.count != 0) {
- /* pool isn't empty: leave it in usedpools */
- UNLOCK();
- return;
- }
- /* Pool is now empty: unlink from usedpools, and
- * link to the front of freepools. This ensures that
- * previously freed pools will be allocated later
- * (being not referenced, they are perhaps paged out).
- */
- next = pool->nextpool;
- prev = pool->prevpool;
- next->prevpool = prev;
- prev->nextpool = next;
-
- /* Link the pool to freepools. This is a singly-linked
- * list, and pool->prevpool isn't used there.
- */
- ao = &arenas[pool->arenaindex];
- pool->nextpool = ao->freepools;
- ao->freepools = pool;
- nf = ++ao->nfreepools;
-
- /* All the rest is arena management. We just freed
- * a pool, and there are 4 cases for arena mgmt:
- * 1. If all the pools are free, return the arena to
- * the system free().
- * 2. If this is the only free pool in the arena,
- * add the arena back to the `usable_arenas` list.
- * 3. If the "next" arena has a smaller count of free
- * pools, we have to "slide this arena right" to
- * restore that usable_arenas is sorted in order of
- * nfreepools.
- * 4. Else there's nothing more to do.
- */
- if (nf == ao->ntotalpools) {
- /* Case 1. First unlink ao from usable_arenas.
- */
- assert(ao->prevarena == NULL ||
- ao->prevarena->address != 0);
- assert(ao ->nextarena == NULL ||
- ao->nextarena->address != 0);
-
- /* Fix the pointer in the prevarena, or the
- * usable_arenas pointer.
- */
- if (ao->prevarena == NULL) {
- usable_arenas = ao->nextarena;
- assert(usable_arenas == NULL ||
- usable_arenas->address != 0);
- }
- else {
- assert(ao->prevarena->nextarena == ao);
- ao->prevarena->nextarena =
- ao->nextarena;
- }
- /* Fix the pointer in the nextarena. */
- if (ao->nextarena != NULL) {
- assert(ao->nextarena->prevarena == ao);
- ao->nextarena->prevarena =
- ao->prevarena;
- }
- /* Record that this arena_object slot is
- * available to be reused.
- */
- ao->nextarena = unused_arena_objects;
- unused_arena_objects = ao;
-
- /* Free the entire arena. */
- free((void *)ao->address);
- ao->address = 0; /* mark unassociated */
- --narenas_currently_allocated;
-
- UNLOCK();
- return;
- }
- if (nf == 1) {
- /* Case 2. Put ao at the head of
- * usable_arenas. Note that because
- * ao->nfreepools was 0 before, ao isn't
- * currently on the usable_arenas list.
- */
- ao->nextarena = usable_arenas;
- ao->prevarena = NULL;
- if (usable_arenas)
- usable_arenas->prevarena = ao;
- usable_arenas = ao;
- assert(usable_arenas->address != 0);
-
- UNLOCK();
- return;
- }
- /* If this arena is now out of order, we need to keep
- * the list sorted. The list is kept sorted so that
- * the "most full" arenas are used first, which allows
- * the nearly empty arenas to be completely freed. In
- * a few un-scientific tests, it seems like this
- * approach allowed a lot more memory to be freed.
- */
- if (ao->nextarena == NULL ||
- nf <= ao->nextarena->nfreepools) {
- /* Case 4. Nothing to do. */
- UNLOCK();
- return;
- }
- /* Case 3: We have to move the arena towards the end
- * of the list, because it has more free pools than
- * the arena to its right.
- * First unlink ao from usable_arenas.
- */
- if (ao->prevarena != NULL) {
- /* ao isn't at the head of the list */
- assert(ao->prevarena->nextarena == ao);
- ao->prevarena->nextarena = ao->nextarena;
- }
- else {
- /* ao is at the head of the list */
- assert(usable_arenas == ao);
- usable_arenas = ao->nextarena;
- }
- ao->nextarena->prevarena = ao->prevarena;
-
- /* Locate the new insertion point by iterating over
- * the list, using our nextarena pointer.
- */
- while (ao->nextarena != NULL &&
- nf > ao->nextarena->nfreepools) {
- ao->prevarena = ao->nextarena;
- ao->nextarena = ao->nextarena->nextarena;
- }
-
- /* Insert ao at this point. */
- assert(ao->nextarena == NULL ||
- ao->prevarena == ao->nextarena->prevarena);
- assert(ao->prevarena->nextarena == ao->nextarena);
-
- ao->prevarena->nextarena = ao;
- if (ao->nextarena != NULL)
- ao->nextarena->prevarena = ao;
-
- /* Verify that the swaps worked. */
- assert(ao->nextarena == NULL ||
- nf <= ao->nextarena->nfreepools);
- assert(ao->prevarena == NULL ||
- nf > ao->prevarena->nfreepools);
- assert(ao->nextarena == NULL ||
- ao->nextarena->prevarena == ao);
- assert((usable_arenas == ao &&
- ao->prevarena == NULL) ||
- ao->prevarena->nextarena == ao);
-
- UNLOCK();
- return;
- }
- /* Pool was full, so doesn't currently live in any list:
- * link it to the front of the appropriate usedpools[] list.
- * This mimics LRU pool usage for new allocations and
- * targets optimal filling when several pools contain
- * blocks of the same size class.
- */
- --pool->ref.count;
- assert(pool->ref.count > 0); /* else the pool is empty */
- size = pool->szidx;
- next = usedpools[size + size];
- prev = next->prevpool;
- /* insert pool before next: prev <-> pool <-> next */
- pool->nextpool = next;
- pool->prevpool = prev;
- next->prevpool = pool;
- prev->nextpool = pool;
- UNLOCK();
- return;
- }
-
- /* We didn't allocate this address. */
- free(p);
-}
-
-/* realloc. If p is NULL, this acts like malloc(nbytes). Else if nbytes==0,
- * then as the Python docs promise, we do not treat this like free(p), and
- * return a non-NULL result.
- */
-
-#undef PyObject_Realloc
-void *
-PyObject_Realloc(void *p, size_t nbytes)
-{
- void *bp;
- poolp pool;
- size_t size;
-
- if (p == NULL)
- return PyObject_Malloc(nbytes);
-
- pool = POOL_ADDR(p);
- if (Py_ADDRESS_IN_RANGE(p, pool)) {
- /* We're in charge of this block */
- size = INDEX2SIZE(pool->szidx);
- if (nbytes <= size) {
- /* The block is staying the same or shrinking. If
- * it's shrinking, there's a tradeoff: it costs
- * cycles to copy the block to a smaller size class,
- * but it wastes memory not to copy it. The
- * compromise here is to copy on shrink only if at
- * least 25% of size can be shaved off.
- */
- if (4 * nbytes > 3 * size) {
- /* It's the same,
- * or shrinking and new/old > 3/4.
- */
- return p;
- }
- size = nbytes;
- }
- bp = PyObject_Malloc(nbytes);
- if (bp != NULL) {
- memcpy(bp, p, size);
- PyObject_Free(p);
- }
- return bp;
- }
- /* We're not managing this block. If nbytes <=
- * SMALL_REQUEST_THRESHOLD, it's tempting to try to take over this
- * block. However, if we do, we need to copy the valid data from
- * the C-managed block to one of our blocks, and there's no portable
- * way to know how much of the memory space starting at p is valid.
- * As bug 1185883 pointed out the hard way, it's possible that the
- * C-managed block is "at the end" of allocated VM space, so that
- * a memory fault can occur if we try to copy nbytes bytes starting
- * at p. Instead we punt: let C continue to manage this block.
- */
- if (nbytes)
- return realloc(p, nbytes);
- /* C doesn't define the result of realloc(p, 0) (it may or may not
- * return NULL then), but Python's docs promise that nbytes==0 never
- * returns NULL. We don't pass 0 to realloc(), to avoid that endcase
- * to begin with. Even then, we can't be sure that realloc() won't
- * return NULL.
- */
- bp = realloc(p, 1);
- return bp ? bp : p;
-}
-
-#else /* ! WITH_PYMALLOC */
-
-/*==========================================================================*/
-/* pymalloc not enabled: Redirect the entry points to malloc. These will
- * only be used by extensions that are compiled with pymalloc enabled. */
-
-void *
-PyObject_Malloc(size_t n)
-{
- return PyMem_MALLOC(n);
-}
-
-void *
-PyObject_Realloc(void *p, size_t n)
-{
- return PyMem_REALLOC(p, n);
-}
-
-void
-PyObject_Free(void *p)
-{
- PyMem_FREE(p);
-}
-#endif /* WITH_PYMALLOC */
-
-#ifdef PYMALLOC_DEBUG
-/*==========================================================================*/
-/* A x-platform debugging allocator. This doesn't manage memory directly,
- * it wraps a real allocator, adding extra debugging info to the memory blocks.
- */
-
-/* Special bytes broadcast into debug memory blocks at appropriate times.
- * Strings of these are unlikely to be valid addresses, floats, ints or
- * 7-bit ASCII.
- */
-#undef CLEANBYTE
-#undef DEADBYTE
-#undef FORBIDDENBYTE
-#define CLEANBYTE 0xCB /* clean (newly allocated) memory */
-#define DEADBYTE 0xDB /* dead (newly freed) memory */
-#define FORBIDDENBYTE 0xFB /* untouchable bytes at each end of a block */
-
-static size_t serialno = 0; /* incremented on each debug {m,re}alloc */
-
-/* serialno is always incremented via calling this routine. The point is
- * to supply a single place to set a breakpoint.
- */
-static void
-bumpserialno(void)
-{
- ++serialno;
-}
-
-#define SST SIZEOF_SIZE_T
-
-/* Read sizeof(size_t) bytes at p as a big-endian size_t. */
-static size_t
-read_size_t(const void *p)
-{
- const uchar *q = (const uchar *)p;
- size_t result = *q++;
- int i;
-
- for (i = SST; --i > 0; ++q)
- result = (result << 8) | *q;
- return result;
-}
-
-/* Write n as a big-endian size_t, MSB at address p, LSB at
- * p + sizeof(size_t) - 1.
- */
-static void
-write_size_t(void *p, size_t n)
-{
- uchar *q = (uchar *)p + SST - 1;
- int i;
-
- for (i = SST; --i >= 0; --q) {
- *q = (uchar)(n & 0xff);
- n >>= 8;
- }
-}
-
-#ifdef Py_DEBUG
-/* Is target in the list? The list is traversed via the nextpool pointers.
- * The list may be NULL-terminated, or circular. Return 1 if target is in
- * list, else 0.
- */
-static int
-pool_is_in_list(const poolp target, poolp list)
-{
- poolp origlist = list;
- assert(target != NULL);
- if (list == NULL)
- return 0;
- do {
- if (target == list)
- return 1;
- list = list->nextpool;
- } while (list != NULL && list != origlist);
- return 0;
-}
-
-#else
-#define pool_is_in_list(X, Y) 1
-
-#endif /* Py_DEBUG */
-
-/* Let S = sizeof(size_t). The debug malloc asks for 4*S extra bytes and
- fills them with useful stuff, here calling the underlying malloc's result p:
-
-p[0: S]
- Number of bytes originally asked for. This is a size_t, big-endian (easier
- to read in a memory dump).
-p[S: 2*S]
- Copies of FORBIDDENBYTE. Used to catch under- writes and reads.
-p[2*S: 2*S+n]
- The requested memory, filled with copies of CLEANBYTE.
- Used to catch reference to uninitialized memory.
- &p[2*S] is returned. Note that this is 8-byte aligned if pymalloc
- handled the request itself.
-p[2*S+n: 2*S+n+S]
- Copies of FORBIDDENBYTE. Used to catch over- writes and reads.
-p[2*S+n+S: 2*S+n+2*S]
- A serial number, incremented by 1 on each call to _PyObject_DebugMalloc
- and _PyObject_DebugRealloc.
- This is a big-endian size_t.
- If "bad memory" is detected later, the serial number gives an
- excellent way to set a breakpoint on the next run, to capture the
- instant at which this block was passed out.
-*/
-
-void *
-_PyObject_DebugMalloc(size_t nbytes)
-{
- uchar *p; /* base address of malloc'ed block */
- uchar *tail; /* p + 2*SST + nbytes == pointer to tail pad bytes */
- size_t total; /* nbytes + 4*SST */
-
- bumpserialno();
- total = nbytes + 4*SST;
- if (total < nbytes)
- /* overflow: can't represent total as a size_t */
- return NULL;
-
- p = (uchar *)PyObject_Malloc(total);
- if (p == NULL)
- return NULL;
-
- write_size_t(p, nbytes);
- memset(p + SST, FORBIDDENBYTE, SST);
-
- if (nbytes > 0)
- memset(p + 2*SST, CLEANBYTE, nbytes);
-
- tail = p + 2*SST + nbytes;
- memset(tail, FORBIDDENBYTE, SST);
- write_size_t(tail + SST, serialno);
-
- return p + 2*SST;
-}
-
-/* The debug free first checks the 2*SST bytes on each end for sanity (in
- particular, that the FORBIDDENBYTEs are still intact).
- Then fills the original bytes with DEADBYTE.
- Then calls the underlying free.
-*/
-void
-_PyObject_DebugFree(void *p)
-{
- uchar *q = (uchar *)p - 2*SST; /* address returned from malloc */
- size_t nbytes;
-
- if (p == NULL)
- return;
- _PyObject_DebugCheckAddress(p);
- nbytes = read_size_t(q);
- if (nbytes > 0)
- memset(q, DEADBYTE, nbytes);
- PyObject_Free(q);
-}
-
-void *
-_PyObject_DebugRealloc(void *p, size_t nbytes)
-{
- uchar *q = (uchar *)p;
- uchar *tail;
- size_t total; /* nbytes + 4*SST */
- size_t original_nbytes;
- int i;
-
- if (p == NULL)
- return _PyObject_DebugMalloc(nbytes);
-
- _PyObject_DebugCheckAddress(p);
- bumpserialno();
- original_nbytes = read_size_t(q - 2*SST);
- total = nbytes + 4*SST;
- if (total < nbytes)
- /* overflow: can't represent total as a size_t */
- return NULL;
-
- if (nbytes < original_nbytes) {
- /* shrinking: mark old extra memory dead */
- memset(q + nbytes, DEADBYTE, original_nbytes - nbytes);
- }
-
- /* Resize and add decorations. */
- q = (uchar *)PyObject_Realloc(q - 2*SST, total);
- if (q == NULL)
- return NULL;
-
- write_size_t(q, nbytes);
- for (i = 0; i < SST; ++i)
- assert(q[SST + i] == FORBIDDENBYTE);
- q += 2*SST;
- tail = q + nbytes;
- memset(tail, FORBIDDENBYTE, SST);
- write_size_t(tail + SST, serialno);
-
- if (nbytes > original_nbytes) {
- /* growing: mark new extra memory clean */
- memset(q + original_nbytes, CLEANBYTE,
- nbytes - original_nbytes);
- }
-
- return q;
-}
-
-/* Check the forbidden bytes on both ends of the memory allocated for p.
- * If anything is wrong, print info to stderr via _PyObject_DebugDumpAddress,
- * and call Py_FatalError to kill the program.
- */
- void
-_PyObject_DebugCheckAddress(const void *p)
-{
- const uchar *q = (const uchar *)p;
- char *msg;
- size_t nbytes;
- const uchar *tail;
- int i;
-
- if (p == NULL) {
- msg = "didn't expect a NULL pointer";
- goto error;
- }
-
- /* Check the stuff at the start of p first: if there's underwrite
- * corruption, the number-of-bytes field may be nuts, and checking
- * the tail could lead to a segfault then.
- */
- for (i = SST; i >= 1; --i) {
- if (*(q-i) != FORBIDDENBYTE) {
- msg = "bad leading pad byte";
- goto error;
- }
- }
-
- nbytes = read_size_t(q - 2*SST);
- tail = q + nbytes;
- for (i = 0; i < SST; ++i) {
- if (tail[i] != FORBIDDENBYTE) {
- msg = "bad trailing pad byte";
- goto error;
- }
- }
-
- return;
-
-error:
- _PyObject_DebugDumpAddress(p);
- Py_FatalError(msg);
-}
-
-/* Display info to stderr about the memory block at p. */
-void
-_PyObject_DebugDumpAddress(const void *p)
-{
- const uchar *q = (const uchar *)p;
- const uchar *tail;
- size_t nbytes, serial;
- int i;
- int ok;
-
- fprintf(stderr, "Debug memory block at address p=%p:\n", p);
- if (p == NULL)
- return;
-
- nbytes = read_size_t(q - 2*SST);
- fprintf(stderr, " %" PY_FORMAT_SIZE_T "u bytes originally "
- "requested\n", nbytes);
-
- /* In case this is nuts, check the leading pad bytes first. */
- fprintf(stderr, " The %d pad bytes at p-%d are ", SST, SST);
- ok = 1;
- for (i = 1; i <= SST; ++i) {
- if (*(q-i) != FORBIDDENBYTE) {
- ok = 0;
- break;
- }
- }
- if (ok)
- fputs("FORBIDDENBYTE, as expected.\n", stderr);
- else {
- fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
- FORBIDDENBYTE);
- for (i = SST; i >= 1; --i) {
- const uchar byte = *(q-i);
- fprintf(stderr, " at p-%d: 0x%02x", i, byte);
- if (byte != FORBIDDENBYTE)
- fputs(" *** OUCH", stderr);
- fputc('\n', stderr);
- }
-
- fputs(" Because memory is corrupted at the start, the "
- "count of bytes requested\n"
- " may be bogus, and checking the trailing pad "
- "bytes may segfault.\n", stderr);
- }
-
- tail = q + nbytes;
- fprintf(stderr, " The %d pad bytes at tail=%p are ", SST, tail);
- ok = 1;
- for (i = 0; i < SST; ++i) {
- if (tail[i] != FORBIDDENBYTE) {
- ok = 0;
- break;
- }
- }
- if (ok)
- fputs("FORBIDDENBYTE, as expected.\n", stderr);
- else {
- fprintf(stderr, "not all FORBIDDENBYTE (0x%02x):\n",
- FORBIDDENBYTE);
- for (i = 0; i < SST; ++i) {
- const uchar byte = tail[i];
- fprintf(stderr, " at tail+%d: 0x%02x",
- i, byte);
- if (byte != FORBIDDENBYTE)
- fputs(" *** OUCH", stderr);
- fputc('\n', stderr);
- }
- }
-
- serial = read_size_t(tail + SST);
- fprintf(stderr, " The block was made by call #%" PY_FORMAT_SIZE_T
- "u to debug malloc/realloc.\n", serial);
-
- if (nbytes > 0) {
- i = 0;
- fputs(" Data at p:", stderr);
- /* print up to 8 bytes at the start */
- while (q < tail && i < 8) {
- fprintf(stderr, " %02x", *q);
- ++i;
- ++q;
- }
- /* and up to 8 at the end */
- if (q < tail) {
- if (tail - q > 8) {
- fputs(" ...", stderr);
- q = tail - 8;
- }
- while (q < tail) {
- fprintf(stderr, " %02x", *q);
- ++q;
- }
- }
- fputc('\n', stderr);
- }
-}
-
-static size_t
-printone(const char* msg, size_t value)
-{
- int i, k;
- char buf[100];
- size_t origvalue = value;
-
- fputs(msg, stderr);
- for (i = (int)strlen(msg); i < 35; ++i)
- fputc(' ', stderr);
- fputc('=', stderr);
-
- /* Write the value with commas. */
- i = 22;
- buf[i--] = '\0';
- buf[i--] = '\n';
- k = 3;
- do {
- size_t nextvalue = value / 10;
- uint digit = (uint)(value - nextvalue * 10);
- value = nextvalue;
- buf[i--] = (char)(digit + '0');
- --k;
- if (k == 0 && value && i >= 0) {
- k = 3;
- buf[i--] = ',';
- }
- } while (value && i >= 0);
-
- while (i >= 0)
- buf[i--] = ' ';
- fputs(buf, stderr);
-
- return origvalue;
-}
-
-/* Print summary info to stderr about the state of pymalloc's structures.
- * In Py_DEBUG mode, also perform some expensive internal consistency
- * checks.
- */
-void
-_PyObject_DebugMallocStats(void)
-{
- uint i;
- const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
- /* # of pools, allocated blocks, and free blocks per class index */
- size_t numpools[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
- size_t numblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
- size_t numfreeblocks[SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT];
- /* total # of allocated bytes in used and full pools */
- size_t allocated_bytes = 0;
- /* total # of available bytes in used pools */
- size_t available_bytes = 0;
- /* # of free pools + pools not yet carved out of current arena */
- uint numfreepools = 0;
- /* # of bytes for arena alignment padding */
- size_t arena_alignment = 0;
- /* # of bytes in used and full pools used for pool_headers */
- size_t pool_header_bytes = 0;
- /* # of bytes in used and full pools wasted due to quantization,
- * i.e. the necessarily leftover space at the ends of used and
- * full pools.
- */
- size_t quantization = 0;
- /* # of arenas actually allocated. */
- size_t narenas = 0;
- /* running total -- should equal narenas * ARENA_SIZE */
- size_t total;
- char buf[128];
-
- fprintf(stderr, "Small block threshold = %d, in %u size classes.\n",
- SMALL_REQUEST_THRESHOLD, numclasses);
-
- for (i = 0; i < numclasses; ++i)
- numpools[i] = numblocks[i] = numfreeblocks[i] = 0;
-
- /* Because full pools aren't linked to from anything, it's easiest
- * to march over all the arenas. If we're lucky, most of the memory
- * will be living in full pools -- would be a shame to miss them.
- */
- for (i = 0; i < maxarenas; ++i) {
- uint poolsinarena;
- uint j;
- uptr base = arenas[i].address;
-
- /* Skip arenas which are not allocated. */
- if (arenas[i].address == (uptr)NULL)
- continue;
- narenas += 1;
-
- poolsinarena = arenas[i].ntotalpools;
- numfreepools += arenas[i].nfreepools;
-
- /* round up to pool alignment */
- if (base & (uptr)POOL_SIZE_MASK) {
- arena_alignment += POOL_SIZE;
- base &= ~(uptr)POOL_SIZE_MASK;
- base += POOL_SIZE;
- }
-
- /* visit every pool in the arena */
- assert(base <= (uptr) arenas[i].pool_address);
- for (j = 0;
- base < (uptr) arenas[i].pool_address;
- ++j, base += POOL_SIZE) {
- poolp p = (poolp)base;
- const uint sz = p->szidx;
- uint freeblocks;
-
- if (p->ref.count == 0) {
- /* currently unused */
- assert(pool_is_in_list(p, arenas[i].freepools));
- continue;
- }
- ++numpools[sz];
- numblocks[sz] += p->ref.count;
- freeblocks = NUMBLOCKS(sz) - p->ref.count;
- numfreeblocks[sz] += freeblocks;
-#ifdef Py_DEBUG
- if (freeblocks > 0)
- assert(pool_is_in_list(p, usedpools[sz + sz]));
-#endif
- }
- }
- assert(narenas == narenas_currently_allocated);
-
- fputc('\n', stderr);
- fputs("class size num pools blocks in use avail blocks\n"
- "----- ---- --------- ------------- ------------\n",
- stderr);
-
- for (i = 0; i < numclasses; ++i) {
- size_t p = numpools[i];
- size_t b = numblocks[i];
- size_t f = numfreeblocks[i];
- uint size = INDEX2SIZE(i);
- if (p == 0) {
- assert(b == 0 && f == 0);
- continue;
- }
- fprintf(stderr, "%5u %6u "
- "%11" PY_FORMAT_SIZE_T "u "
- "%15" PY_FORMAT_SIZE_T "u "
- "%13" PY_FORMAT_SIZE_T "u\n",
- i, size, p, b, f);
- allocated_bytes += b * size;
- available_bytes += f * size;
- pool_header_bytes += p * POOL_OVERHEAD;
- quantization += p * ((POOL_SIZE - POOL_OVERHEAD) % size);
- }
- fputc('\n', stderr);
- (void)printone("# times object malloc called", serialno);
-
- (void)printone("# arenas allocated total", ntimes_arena_allocated);
- (void)printone("# arenas reclaimed", ntimes_arena_allocated - narenas);
- (void)printone("# arenas highwater mark", narenas_highwater);
- (void)printone("# arenas allocated current", narenas);
-
- PyOS_snprintf(buf, sizeof(buf),
- "%" PY_FORMAT_SIZE_T "u arenas * %d bytes/arena",
- narenas, ARENA_SIZE);
- (void)printone(buf, narenas * ARENA_SIZE);
-
- fputc('\n', stderr);
-
- total = printone("# bytes in allocated blocks", allocated_bytes);
- total += printone("# bytes in available blocks", available_bytes);
-
- PyOS_snprintf(buf, sizeof(buf),
- "%u unused pools * %d bytes", numfreepools, POOL_SIZE);
- total += printone(buf, (size_t)numfreepools * POOL_SIZE);
-
- total += printone("# bytes lost to pool headers", pool_header_bytes);
- total += printone("# bytes lost to quantization", quantization);
- total += printone("# bytes lost to arena alignment", arena_alignment);
- (void)printone("Total", total);
-}
-
-#endif /* PYMALLOC_DEBUG */
-
-#ifdef Py_USING_MEMORY_DEBUGGER
-/* Make this function last so gcc won't inline it since the definition is
- * after the reference.
- */
-int
-Py_ADDRESS_IN_RANGE(void *P, poolp pool)
-{
- return pool->arenaindex < maxarenas &&
- (uptr)P - arenas[pool->arenaindex].address < (uptr)ARENA_SIZE &&
- arenas[pool->arenaindex].address != 0;
-}
-#endif
diff --git a/sys/src/cmd/python/Objects/rangeobject.c b/sys/src/cmd/python/Objects/rangeobject.c
deleted file mode 100644
index c48bee016..000000000
--- a/sys/src/cmd/python/Objects/rangeobject.c
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Range object implementation */
-
-#include "Python.h"
-
-typedef struct {
- PyObject_HEAD
- long start;
- long step;
- long len;
-} rangeobject;
-
-/* Return number of items in range/xrange (lo, hi, step). step > 0
- * required. Return a value < 0 if & only if the true value is too
- * large to fit in a signed long.
- */
-static long
-get_len_of_range(long lo, long hi, long step)
-{
- /* -------------------------------------------------------------
- If lo >= hi, the range is empty.
- Else if n values are in the range, the last one is
- lo + (n-1)*step, which must be <= hi-1. Rearranging,
- n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives
- the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so
- the RHS is non-negative and so truncation is the same as the
- floor. Letting M be the largest positive long, the worst case
- for the RHS numerator is hi=M, lo=-M-1, and then
- hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough
- precision to compute the RHS exactly.
- ---------------------------------------------------------------*/
- long n = 0;
- if (lo < hi) {
- unsigned long uhi = (unsigned long)hi;
- unsigned long ulo = (unsigned long)lo;
- unsigned long diff = uhi - ulo - 1;
- n = (long)(diff / (unsigned long)step + 1);
- }
- return n;
-}
-
-static PyObject *
-range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
-{
- rangeobject *obj;
- long ilow = 0, ihigh = 0, istep = 1;
- long n;
-
- if (!_PyArg_NoKeywords("xrange()", kw))
- return NULL;
-
- if (PyTuple_Size(args) <= 1) {
- if (!PyArg_ParseTuple(args,
- "l;xrange() requires 1-3 int arguments",
- &ihigh))
- return NULL;
- }
- else {
- if (!PyArg_ParseTuple(args,
- "ll|l;xrange() requires 1-3 int arguments",
- &ilow, &ihigh, &istep))
- return NULL;
- }
- if (istep == 0) {
- PyErr_SetString(PyExc_ValueError, "xrange() arg 3 must not be zero");
- return NULL;
- }
- if (istep > 0)
- n = get_len_of_range(ilow, ihigh, istep);
- else
- n = get_len_of_range(ihigh, ilow, -istep);
- if (n < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "xrange() result has too many items");
- return NULL;
- }
-
- obj = PyObject_New(rangeobject, &PyRange_Type);
- if (obj == NULL)
- return NULL;
- obj->start = ilow;
- obj->len = n;
- obj->step = istep;
- return (PyObject *) obj;
-}
-
-PyDoc_STRVAR(range_doc,
-"xrange([start,] stop[, step]) -> xrange object\n\
-\n\
-Like range(), but instead of returning a list, returns an object that\n\
-generates the numbers in the range on demand. For looping, this is \n\
-slightly faster than range() and more memory efficient.");
-
-static PyObject *
-range_item(rangeobject *r, Py_ssize_t i)
-{
- if (i < 0 || i >= r->len) {
- PyErr_SetString(PyExc_IndexError,
- "xrange object index out of range");
- return NULL;
- }
- return PyInt_FromSsize_t(r->start + (i % r->len) * r->step);
-}
-
-static Py_ssize_t
-range_length(rangeobject *r)
-{
- return (Py_ssize_t)(r->len);
-}
-
-static PyObject *
-range_repr(rangeobject *r)
-{
- PyObject *rtn;
-
- if (r->start == 0 && r->step == 1)
- rtn = PyString_FromFormat("xrange(%ld)",
- r->start + r->len * r->step);
-
- else if (r->step == 1)
- rtn = PyString_FromFormat("xrange(%ld, %ld)",
- r->start,
- r->start + r->len * r->step);
-
- else
- rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)",
- r->start,
- r->start + r->len * r->step,
- r->step);
- return rtn;
-}
-
-static PySequenceMethods range_as_sequence = {
- (lenfunc)range_length, /* sq_length */
- 0, /* sq_concat */
- 0, /* sq_repeat */
- (ssizeargfunc)range_item, /* sq_item */
- 0, /* sq_slice */
-};
-
-static PyObject * range_iter(PyObject *seq);
-static PyObject * range_reverse(PyObject *seq);
-
-PyDoc_STRVAR(reverse_doc,
-"Returns a reverse iterator.");
-
-static PyMethodDef range_methods[] = {
- {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, reverse_doc},
- {NULL, NULL} /* sentinel */
-};
-
-PyTypeObject PyRange_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* Number of items for varobject */
- "xrange", /* Name of this type */
- sizeof(rangeobject), /* Basic object size */
- 0, /* Item size for varobject */
- (destructor)PyObject_Del, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)range_repr, /* tp_repr */
- 0, /* tp_as_number */
- &range_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- range_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- range_iter, /* tp_iter */
- 0, /* tp_iternext */
- range_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- range_new, /* tp_new */
-};
-
-/*********************** Xrange Iterator **************************/
-
-typedef struct {
- PyObject_HEAD
- long index;
- long start;
- long step;
- long len;
-} rangeiterobject;
-
-static PyObject *
-rangeiter_next(rangeiterobject *r)
-{
- if (r->index < r->len)
- return PyInt_FromLong(r->start + (r->index++) * r->step);
- return NULL;
-}
-
-static PyObject *
-rangeiter_len(rangeiterobject *r)
-{
- return PyInt_FromLong(r->len - r->index);
-}
-
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
-
-static PyMethodDef rangeiter_methods[] = {
- {"__length_hint__", (PyCFunction)rangeiter_len, METH_NOARGS, length_hint_doc},
- {NULL, NULL} /* sentinel */
-};
-
-static PyTypeObject Pyrangeiter_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "rangeiterator", /* tp_name */
- sizeof(rangeiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)PyObject_Del, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)rangeiter_next, /* tp_iternext */
- rangeiter_methods, /* tp_methods */
- 0,
-};
-
-static PyObject *
-range_iter(PyObject *seq)
-{
- rangeiterobject *it;
-
- if (!PyRange_Check(seq)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);
- if (it == NULL)
- return NULL;
- it->index = 0;
- it->start = ((rangeobject *)seq)->start;
- it->step = ((rangeobject *)seq)->step;
- it->len = ((rangeobject *)seq)->len;
- return (PyObject *)it;
-}
-
-static PyObject *
-range_reverse(PyObject *seq)
-{
- rangeiterobject *it;
- long start, step, len;
-
- if (!PyRange_Check(seq)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- it = PyObject_New(rangeiterobject, &Pyrangeiter_Type);
- if (it == NULL)
- return NULL;
-
- start = ((rangeobject *)seq)->start;
- step = ((rangeobject *)seq)->step;
- len = ((rangeobject *)seq)->len;
-
- it->index = 0;
- it->start = start + (len-1) * step;
- it->step = -step;
- it->len = len;
-
- return (PyObject *)it;
-}
diff --git a/sys/src/cmd/python/Objects/setobject.c b/sys/src/cmd/python/Objects/setobject.c
deleted file mode 100644
index b336fba7a..000000000
--- a/sys/src/cmd/python/Objects/setobject.c
+++ /dev/null
@@ -1,2312 +0,0 @@
-
-/* set object implementation
- Written and maintained by Raymond D. Hettinger <python@rcn.com>
- Derived from Lib/sets.py and Objects/dictobject.c.
-
- Copyright (c) 2003-6 Python Software Foundation.
- All rights reserved.
-*/
-
-#include "Python.h"
-#include "structmember.h"
-
-/* Set a key error with the specified argument, wrapping it in a
- * tuple automatically so that tuple keys are not unpacked as the
- * exception arguments. */
-static void
-set_key_error(PyObject *arg)
-{
- PyObject *tup;
- tup = PyTuple_Pack(1, arg);
- if (!tup)
- return; /* caller will expect error to be set anyway */
- PyErr_SetObject(PyExc_KeyError, tup);
- Py_DECREF(tup);
-}
-
-/* This must be >= 1. */
-#define PERTURB_SHIFT 5
-
-/* Object used as dummy key to fill deleted entries */
-static PyObject *dummy = NULL; /* Initialized by first call to make_new_set() */
-
-#ifdef Py_REF_DEBUG
-PyObject *
-_PySet_Dummy(void)
-{
- return dummy;
-}
-#endif
-
-#define INIT_NONZERO_SET_SLOTS(so) do { \
- (so)->table = (so)->smalltable; \
- (so)->mask = PySet_MINSIZE - 1; \
- (so)->hash = -1; \
- } while(0)
-
-#define EMPTY_TO_MINSIZE(so) do { \
- memset((so)->smalltable, 0, sizeof((so)->smalltable)); \
- (so)->used = (so)->fill = 0; \
- INIT_NONZERO_SET_SLOTS(so); \
- } while(0)
-
-/* Reuse scheme to save calls to malloc, free, and memset */
-#define MAXFREESETS 80
-static PySetObject *free_sets[MAXFREESETS];
-static int num_free_sets = 0;
-
-/*
-The basic lookup function used by all operations.
-This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
-Open addressing is preferred over chaining since the link overhead for
-chaining would be substantial (100% with typical malloc overhead).
-
-The initial probe index is computed as hash mod the table size. Subsequent
-probe indices are computed as explained in Objects/dictobject.c.
-
-All arithmetic on hash should ignore overflow.
-
-Unlike the dictionary implementation, the lookkey functions can return
-NULL if the rich comparison returns an error.
-*/
-
-static setentry *
-set_lookkey(PySetObject *so, PyObject *key, register long hash)
-{
- register Py_ssize_t i;
- register size_t perturb;
- register setentry *freeslot;
- register size_t mask = so->mask;
- setentry *table = so->table;
- register setentry *entry;
- register int cmp;
- PyObject *startkey;
-
- i = hash & mask;
- entry = &table[i];
- if (entry->key == NULL || entry->key == key)
- return entry;
-
- if (entry->key == dummy)
- freeslot = entry;
- else {
- if (entry->hash == hash) {
- startkey = entry->key;
- cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
- if (cmp < 0)
- return NULL;
- if (table == so->table && entry->key == startkey) {
- if (cmp > 0)
- return entry;
- }
- else {
- /* The compare did major nasty stuff to the
- * set: start over.
- */
- return set_lookkey(so, key, hash);
- }
- }
- freeslot = NULL;
- }
-
- /* In the loop, key == dummy is by far (factor of 100s) the
- least likely outcome, so test for that last. */
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- entry = &table[i & mask];
- if (entry->key == NULL) {
- if (freeslot != NULL)
- entry = freeslot;
- break;
- }
- if (entry->key == key)
- break;
- if (entry->hash == hash && entry->key != dummy) {
- startkey = entry->key;
- cmp = PyObject_RichCompareBool(startkey, key, Py_EQ);
- if (cmp < 0)
- return NULL;
- if (table == so->table && entry->key == startkey) {
- if (cmp > 0)
- break;
- }
- else {
- /* The compare did major nasty stuff to the
- * set: start over.
- */
- return set_lookkey(so, key, hash);
- }
- }
- else if (entry->key == dummy && freeslot == NULL)
- freeslot = entry;
- }
- return entry;
-}
-
-/*
- * Hacked up version of set_lookkey which can assume keys are always strings;
- * This means we can always use _PyString_Eq directly and not have to check to
- * see if the comparison altered the table.
- */
-static setentry *
-set_lookkey_string(PySetObject *so, PyObject *key, register long hash)
-{
- register Py_ssize_t i;
- register size_t perturb;
- register setentry *freeslot;
- register size_t mask = so->mask;
- setentry *table = so->table;
- register setentry *entry;
-
- /* Make sure this function doesn't have to handle non-string keys,
- including subclasses of str; e.g., one reason to subclass
- strings is to override __eq__, and for speed we don't cater to
- that here. */
- if (!PyString_CheckExact(key)) {
- so->lookup = set_lookkey;
- return set_lookkey(so, key, hash);
- }
- i = hash & mask;
- entry = &table[i];
- if (entry->key == NULL || entry->key == key)
- return entry;
- if (entry->key == dummy)
- freeslot = entry;
- else {
- if (entry->hash == hash && _PyString_Eq(entry->key, key))
- return entry;
- freeslot = NULL;
- }
-
- /* In the loop, key == dummy is by far (factor of 100s) the
- least likely outcome, so test for that last. */
- for (perturb = hash; ; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- entry = &table[i & mask];
- if (entry->key == NULL)
- return freeslot == NULL ? entry : freeslot;
- if (entry->key == key
- || (entry->hash == hash
- && entry->key != dummy
- && _PyString_Eq(entry->key, key)))
- return entry;
- if (entry->key == dummy && freeslot == NULL)
- freeslot = entry;
- }
- assert(0); /* NOT REACHED */
- return 0;
-}
-
-/*
-Internal routine to insert a new key into the table.
-Used by the public insert routine.
-Eats a reference to key.
-*/
-static int
-set_insert_key(register PySetObject *so, PyObject *key, long hash)
-{
- register setentry *entry;
- typedef setentry *(*lookupfunc)(PySetObject *, PyObject *, long);
-
- assert(so->lookup != NULL);
- entry = so->lookup(so, key, hash);
- if (entry == NULL)
- return -1;
- if (entry->key == NULL) {
- /* UNUSED */
- so->fill++;
- entry->key = key;
- entry->hash = hash;
- so->used++;
- } else if (entry->key == dummy) {
- /* DUMMY */
- entry->key = key;
- entry->hash = hash;
- so->used++;
- Py_DECREF(dummy);
- } else {
- /* ACTIVE */
- Py_DECREF(key);
- }
- return 0;
-}
-
-/*
-Internal routine used by set_table_resize() to insert an item which is
-known to be absent from the set. This routine also assumes that
-the set contains no deleted entries. Besides the performance benefit,
-using set_insert_clean() in set_table_resize() is dangerous (SF bug #1456209).
-Note that no refcounts are changed by this routine; if needed, the caller
-is responsible for incref'ing `key`.
-*/
-static void
-set_insert_clean(register PySetObject *so, PyObject *key, long hash)
-{
- register size_t i;
- register size_t perturb;
- register size_t mask = (size_t)so->mask;
- setentry *table = so->table;
- register setentry *entry;
-
- i = hash & mask;
- entry = &table[i];
- for (perturb = hash; entry->key != NULL; perturb >>= PERTURB_SHIFT) {
- i = (i << 2) + i + perturb + 1;
- entry = &table[i & mask];
- }
- so->fill++;
- entry->key = key;
- entry->hash = hash;
- so->used++;
-}
-
-/*
-Restructure the table by allocating a new table and reinserting all
-keys again. When entries have been deleted, the new table may
-actually be smaller than the old one.
-*/
-static int
-set_table_resize(PySetObject *so, Py_ssize_t minused)
-{
- Py_ssize_t newsize;
- setentry *oldtable, *newtable, *entry;
- Py_ssize_t i;
- int is_oldtable_malloced;
- setentry small_copy[PySet_MINSIZE];
-
- assert(minused >= 0);
-
- /* Find the smallest table size > minused. */
- for (newsize = PySet_MINSIZE;
- newsize <= minused && newsize > 0;
- newsize <<= 1)
- ;
- if (newsize <= 0) {
- PyErr_NoMemory();
- return -1;
- }
-
- /* Get space for a new table. */
- oldtable = so->table;
- assert(oldtable != NULL);
- is_oldtable_malloced = oldtable != so->smalltable;
-
- if (newsize == PySet_MINSIZE) {
- /* A large table is shrinking, or we can't get any smaller. */
- newtable = so->smalltable;
- if (newtable == oldtable) {
- if (so->fill == so->used) {
- /* No dummies, so no point doing anything. */
- return 0;
- }
- /* We're not going to resize it, but rebuild the
- table anyway to purge old dummy entries.
- Subtle: This is *necessary* if fill==size,
- as set_lookkey needs at least one virgin slot to
- terminate failing searches. If fill < size, it's
- merely desirable, as dummies slow searches. */
- assert(so->fill > so->used);
- memcpy(small_copy, oldtable, sizeof(small_copy));
- oldtable = small_copy;
- }
- }
- else {
- newtable = PyMem_NEW(setentry, newsize);
- if (newtable == NULL) {
- PyErr_NoMemory();
- return -1;
- }
- }
-
- /* Make the set empty, using the new table. */
- assert(newtable != oldtable);
- so->table = newtable;
- so->mask = newsize - 1;
- memset(newtable, 0, sizeof(setentry) * newsize);
- so->used = 0;
- i = so->fill;
- so->fill = 0;
-
- /* Copy the data over; this is refcount-neutral for active entries;
- dummy entries aren't copied over, of course */
- for (entry = oldtable; i > 0; entry++) {
- if (entry->key == NULL) {
- /* UNUSED */
- ;
- } else if (entry->key == dummy) {
- /* DUMMY */
- --i;
- assert(entry->key == dummy);
- Py_DECREF(entry->key);
- } else {
- /* ACTIVE */
- --i;
- set_insert_clean(so, entry->key, entry->hash);
- }
- }
-
- if (is_oldtable_malloced)
- PyMem_DEL(oldtable);
- return 0;
-}
-
-/* CAUTION: set_add_key/entry() must guarantee it won't resize the table */
-
-static int
-set_add_entry(register PySetObject *so, setentry *entry)
-{
- register Py_ssize_t n_used;
-
- assert(so->fill <= so->mask); /* at least one empty slot */
- n_used = so->used;
- Py_INCREF(entry->key);
- if (set_insert_key(so, entry->key, entry->hash) == -1) {
- Py_DECREF(entry->key);
- return -1;
- }
- if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2))
- return 0;
- return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
-}
-
-static int
-set_add_key(register PySetObject *so, PyObject *key)
-{
- register long hash;
- register Py_ssize_t n_used;
-
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return -1;
- }
- assert(so->fill <= so->mask); /* at least one empty slot */
- n_used = so->used;
- Py_INCREF(key);
- if (set_insert_key(so, key, hash) == -1) {
- Py_DECREF(key);
- return -1;
- }
- if (!(so->used > n_used && so->fill*3 >= (so->mask+1)*2))
- return 0;
- return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
-}
-
-#define DISCARD_NOTFOUND 0
-#define DISCARD_FOUND 1
-
-static int
-set_discard_entry(PySetObject *so, setentry *oldentry)
-{ register setentry *entry;
- PyObject *old_key;
-
- entry = (so->lookup)(so, oldentry->key, oldentry->hash);
- if (entry == NULL)
- return -1;
- if (entry->key == NULL || entry->key == dummy)
- return DISCARD_NOTFOUND;
- old_key = entry->key;
- Py_INCREF(dummy);
- entry->key = dummy;
- so->used--;
- Py_DECREF(old_key);
- return DISCARD_FOUND;
-}
-
-static int
-set_discard_key(PySetObject *so, PyObject *key)
-{
- register long hash;
- register setentry *entry;
- PyObject *old_key;
-
- assert (PyAnySet_Check(so));
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return -1;
- }
- entry = (so->lookup)(so, key, hash);
- if (entry == NULL)
- return -1;
- if (entry->key == NULL || entry->key == dummy)
- return DISCARD_NOTFOUND;
- old_key = entry->key;
- Py_INCREF(dummy);
- entry->key = dummy;
- so->used--;
- Py_DECREF(old_key);
- return DISCARD_FOUND;
-}
-
-static int
-set_clear_internal(PySetObject *so)
-{
- setentry *entry, *table;
- int table_is_malloced;
- Py_ssize_t fill;
- setentry small_copy[PySet_MINSIZE];
-#ifdef Py_DEBUG
- Py_ssize_t i, n;
- assert (PyAnySet_Check(so));
-
- n = so->mask + 1;
- i = 0;
-#endif
-
- table = so->table;
- assert(table != NULL);
- table_is_malloced = table != so->smalltable;
-
- /* This is delicate. During the process of clearing the set,
- * decrefs can cause the set to mutate. To avoid fatal confusion
- * (voice of experience), we have to make the set empty before
- * clearing the slots, and never refer to anything via so->ref while
- * clearing.
- */
- fill = so->fill;
- if (table_is_malloced)
- EMPTY_TO_MINSIZE(so);
-
- else if (fill > 0) {
- /* It's a small table with something that needs to be cleared.
- * Afraid the only safe way is to copy the set entries into
- * another small table first.
- */
- memcpy(small_copy, table, sizeof(small_copy));
- table = small_copy;
- EMPTY_TO_MINSIZE(so);
- }
- /* else it's a small table that's already empty */
-
- /* Now we can finally clear things. If C had refcounts, we could
- * assert that the refcount on table is 1 now, i.e. that this function
- * has unique access to it, so decref side-effects can't alter it.
- */
- for (entry = table; fill > 0; ++entry) {
-#ifdef Py_DEBUG
- assert(i < n);
- ++i;
-#endif
- if (entry->key) {
- --fill;
- Py_DECREF(entry->key);
- }
-#ifdef Py_DEBUG
- else
- assert(entry->key == NULL);
-#endif
- }
-
- if (table_is_malloced)
- PyMem_DEL(table);
- return 0;
-}
-
-/*
- * Iterate over a set table. Use like so:
- *
- * Py_ssize_t pos;
- * setentry *entry;
- * pos = 0; # important! pos should not otherwise be changed by you
- * while (set_next(yourset, &pos, &entry)) {
- * Refer to borrowed reference in entry->key.
- * }
- *
- * CAUTION: In general, it isn't safe to use set_next in a loop that
- * mutates the table.
- */
-static int
-set_next(PySetObject *so, Py_ssize_t *pos_ptr, setentry **entry_ptr)
-{
- Py_ssize_t i;
- Py_ssize_t mask;
- register setentry *table;
-
- assert (PyAnySet_Check(so));
- i = *pos_ptr;
- assert(i >= 0);
- table = so->table;
- mask = so->mask;
- while (i <= mask && (table[i].key == NULL || table[i].key == dummy))
- i++;
- *pos_ptr = i+1;
- if (i > mask)
- return 0;
- assert(table[i].key != NULL);
- *entry_ptr = &table[i];
- return 1;
-}
-
-static void
-set_dealloc(PySetObject *so)
-{
- register setentry *entry;
- Py_ssize_t fill = so->fill;
- PyObject_GC_UnTrack(so);
- Py_TRASHCAN_SAFE_BEGIN(so)
- if (so->weakreflist != NULL)
- PyObject_ClearWeakRefs((PyObject *) so);
-
- for (entry = so->table; fill > 0; entry++) {
- if (entry->key) {
- --fill;
- Py_DECREF(entry->key);
- }
- }
- if (so->table != so->smalltable)
- PyMem_DEL(so->table);
- if (num_free_sets < MAXFREESETS && PyAnySet_CheckExact(so))
- free_sets[num_free_sets++] = so;
- else
- so->ob_type->tp_free(so);
- Py_TRASHCAN_SAFE_END(so)
-}
-
-static int
-set_tp_print(PySetObject *so, FILE *fp, int flags)
-{
- setentry *entry;
- Py_ssize_t pos=0;
- char *emit = ""; /* No separator emitted on first pass */
- char *separator = ", ";
- int status = Py_ReprEnter((PyObject*)so);
-
- if (status != 0) {
- if (status < 0)
- return status;
- fprintf(fp, "%s(...)", so->ob_type->tp_name);
- return 0;
- }
-
- fprintf(fp, "%s([", so->ob_type->tp_name);
- while (set_next(so, &pos, &entry)) {
- fputs(emit, fp);
- emit = separator;
- if (PyObject_Print(entry->key, fp, 0) != 0) {
- Py_ReprLeave((PyObject*)so);
- return -1;
- }
- }
- fputs("])", fp);
- Py_ReprLeave((PyObject*)so);
- return 0;
-}
-
-static PyObject *
-set_repr(PySetObject *so)
-{
- PyObject *keys, *result=NULL, *listrepr;
- int status = Py_ReprEnter((PyObject*)so);
-
- if (status != 0) {
- if (status < 0)
- return NULL;
- return PyString_FromFormat("%s(...)", so->ob_type->tp_name);
- }
-
- keys = PySequence_List((PyObject *)so);
- if (keys == NULL)
- goto done;
- listrepr = PyObject_Repr(keys);
- Py_DECREF(keys);
- if (listrepr == NULL)
- goto done;
-
- result = PyString_FromFormat("%s(%s)", so->ob_type->tp_name,
- PyString_AS_STRING(listrepr));
- Py_DECREF(listrepr);
-done:
- Py_ReprLeave((PyObject*)so);
- return result;
-}
-
-static Py_ssize_t
-set_len(PyObject *so)
-{
- return ((PySetObject *)so)->used;
-}
-
-static int
-set_merge(PySetObject *so, PyObject *otherset)
-{
- PySetObject *other;
- register Py_ssize_t i;
- register setentry *entry;
-
- assert (PyAnySet_Check(so));
- assert (PyAnySet_Check(otherset));
-
- other = (PySetObject*)otherset;
- if (other == so || other->used == 0)
- /* a.update(a) or a.update({}); nothing to do */
- return 0;
- /* Do one big resize at the start, rather than
- * incrementally resizing as we insert new keys. Expect
- * that there will be no (or few) overlapping keys.
- */
- if ((so->fill + other->used)*3 >= (so->mask+1)*2) {
- if (set_table_resize(so, (so->used + other->used)*2) != 0)
- return -1;
- }
- for (i = 0; i <= other->mask; i++) {
- entry = &other->table[i];
- if (entry->key != NULL &&
- entry->key != dummy) {
- Py_INCREF(entry->key);
- if (set_insert_key(so, entry->key, entry->hash) == -1) {
- Py_DECREF(entry->key);
- return -1;
- }
- }
- }
- return 0;
-}
-
-static int
-set_contains_key(PySetObject *so, PyObject *key)
-{
- long hash;
- setentry *entry;
-
- if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1) {
- hash = PyObject_Hash(key);
- if (hash == -1)
- return -1;
- }
- entry = (so->lookup)(so, key, hash);
- if (entry == NULL)
- return -1;
- key = entry->key;
- return key != NULL && key != dummy;
-}
-
-static int
-set_contains_entry(PySetObject *so, setentry *entry)
-{
- PyObject *key;
- setentry *lu_entry;
-
- lu_entry = (so->lookup)(so, entry->key, entry->hash);
- if (lu_entry == NULL)
- return -1;
- key = lu_entry->key;
- return key != NULL && key != dummy;
-}
-
-static PyObject *
-set_pop(PySetObject *so)
-{
- register Py_ssize_t i = 0;
- register setentry *entry;
- PyObject *key;
-
- assert (PyAnySet_Check(so));
- if (so->used == 0) {
- PyErr_SetString(PyExc_KeyError, "pop from an empty set");
- return NULL;
- }
-
- /* Set entry to "the first" unused or dummy set entry. We abuse
- * the hash field of slot 0 to hold a search finger:
- * If slot 0 has a value, use slot 0.
- * Else slot 0 is being used to hold a search finger,
- * and we use its hash value as the first index to look.
- */
- entry = &so->table[0];
- if (entry->key == NULL || entry->key == dummy) {
- i = entry->hash;
- /* The hash field may be a real hash value, or it may be a
- * legit search finger, or it may be a once-legit search
- * finger that's out of bounds now because it wrapped around
- * or the table shrunk -- simply make sure it's in bounds now.
- */
- if (i > so->mask || i < 1)
- i = 1; /* skip slot 0 */
- while ((entry = &so->table[i])->key == NULL || entry->key==dummy) {
- i++;
- if (i > so->mask)
- i = 1;
- }
- }
- key = entry->key;
- Py_INCREF(dummy);
- entry->key = dummy;
- so->used--;
- so->table[0].hash = i + 1; /* next place to start */
- return key;
-}
-
-PyDoc_STRVAR(pop_doc, "Remove and return an arbitrary set element.");
-
-static int
-set_traverse(PySetObject *so, visitproc visit, void *arg)
-{
- Py_ssize_t pos = 0;
- setentry *entry;
-
- while (set_next(so, &pos, &entry))
- Py_VISIT(entry->key);
- return 0;
-}
-
-static long
-frozenset_hash(PyObject *self)
-{
- PySetObject *so = (PySetObject *)self;
- long h, hash = 1927868237L;
- setentry *entry;
- Py_ssize_t pos = 0;
-
- if (so->hash != -1)
- return so->hash;
-
- hash *= PySet_GET_SIZE(self) + 1;
- while (set_next(so, &pos, &entry)) {
- /* Work to increase the bit dispersion for closely spaced hash
- values. The is important because some use cases have many
- combinations of a small number of elements with nearby
- hashes so that many distinct combinations collapse to only
- a handful of distinct hash values. */
- h = entry->hash;
- hash ^= (h ^ (h << 16) ^ 89869747L) * 3644798167u;
- }
- hash = hash * 69069L + 907133923L;
- if (hash == -1)
- hash = 590923713L;
- so->hash = hash;
- return hash;
-}
-
-static long
-set_nohash(PyObject *self)
-{
- PyErr_SetString(PyExc_TypeError, "set objects are unhashable");
- return -1;
-}
-
-/***** Set iterator type ***********************************************/
-
-typedef struct {
- PyObject_HEAD
- PySetObject *si_set; /* Set to NULL when iterator is exhausted */
- Py_ssize_t si_used;
- Py_ssize_t si_pos;
- Py_ssize_t len;
-} setiterobject;
-
-static void
-setiter_dealloc(setiterobject *si)
-{
- Py_XDECREF(si->si_set);
- PyObject_Del(si);
-}
-
-static PyObject *
-setiter_len(setiterobject *si)
-{
- Py_ssize_t len = 0;
- if (si->si_set != NULL && si->si_used == si->si_set->used)
- len = si->len;
- return PyInt_FromLong(len);
-}
-
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
-
-static PyMethodDef setiter_methods[] = {
- {"__length_hint__", (PyCFunction)setiter_len, METH_NOARGS, length_hint_doc},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *setiter_iternext(setiterobject *si)
-{
- PyObject *key;
- register Py_ssize_t i, mask;
- register setentry *entry;
- PySetObject *so = si->si_set;
-
- if (so == NULL)
- return NULL;
- assert (PyAnySet_Check(so));
-
- if (si->si_used != so->used) {
- PyErr_SetString(PyExc_RuntimeError,
- "Set changed size during iteration");
- si->si_used = -1; /* Make this state sticky */
- return NULL;
- }
-
- i = si->si_pos;
- assert(i>=0);
- entry = so->table;
- mask = so->mask;
- while (i <= mask && (entry[i].key == NULL || entry[i].key == dummy))
- i++;
- si->si_pos = i+1;
- if (i > mask)
- goto fail;
- si->len--;
- key = entry[i].key;
- Py_INCREF(key);
- return key;
-
-fail:
- Py_DECREF(so);
- si->si_set = NULL;
- return NULL;
-}
-
-static PyTypeObject PySetIter_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "setiterator", /* tp_name */
- sizeof(setiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)setiter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- 0, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)setiter_iternext, /* tp_iternext */
- setiter_methods, /* tp_methods */
- 0,
-};
-
-static PyObject *
-set_iter(PySetObject *so)
-{
- setiterobject *si = PyObject_New(setiterobject, &PySetIter_Type);
- if (si == NULL)
- return NULL;
- Py_INCREF(so);
- si->si_set = so;
- si->si_used = so->used;
- si->si_pos = 0;
- si->len = so->used;
- return (PyObject *)si;
-}
-
-static int
-set_update_internal(PySetObject *so, PyObject *other)
-{
- PyObject *key, *it;
-
- if (PyAnySet_Check(other))
- return set_merge(so, other);
-
- if (PyDict_CheckExact(other)) {
- PyObject *value;
- Py_ssize_t pos = 0;
- long hash;
- Py_ssize_t dictsize = PyDict_Size(other);
-
- /* Do one big resize at the start, rather than
- * incrementally resizing as we insert new keys. Expect
- * that there will be no (or few) overlapping keys.
- */
- if (dictsize == -1)
- return -1;
- if ((so->fill + dictsize)*3 >= (so->mask+1)*2) {
- if (set_table_resize(so, (so->used + dictsize)*2) != 0)
- return -1;
- }
- while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
- setentry an_entry;
-
- an_entry.hash = hash;
- an_entry.key = key;
- if (set_add_entry(so, &an_entry) == -1)
- return -1;
- }
- return 0;
- }
-
- it = PyObject_GetIter(other);
- if (it == NULL)
- return -1;
-
- while ((key = PyIter_Next(it)) != NULL) {
- if (set_add_key(so, key) == -1) {
- Py_DECREF(it);
- Py_DECREF(key);
- return -1;
- }
- Py_DECREF(key);
- }
- Py_DECREF(it);
- if (PyErr_Occurred())
- return -1;
- return 0;
-}
-
-static PyObject *
-set_update(PySetObject *so, PyObject *other)
-{
- if (set_update_internal(so, other) == -1)
- return NULL;
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(update_doc,
-"Update a set with the union of itself and another.");
-
-static PyObject *
-make_new_set(PyTypeObject *type, PyObject *iterable)
-{
- register PySetObject *so = NULL;
-
- if (dummy == NULL) { /* Auto-initialize dummy */
- dummy = PyString_FromString("<dummy key>");
- if (dummy == NULL)
- return NULL;
- }
-
- /* create PySetObject structure */
- if (num_free_sets &&
- (type == &PySet_Type || type == &PyFrozenSet_Type)) {
- so = free_sets[--num_free_sets];
- assert (so != NULL && PyAnySet_CheckExact(so));
- so->ob_type = type;
- _Py_NewReference((PyObject *)so);
- EMPTY_TO_MINSIZE(so);
- PyObject_GC_Track(so);
- } else {
- so = (PySetObject *)type->tp_alloc(type, 0);
- if (so == NULL)
- return NULL;
- /* tp_alloc has already zeroed the structure */
- assert(so->table == NULL && so->fill == 0 && so->used == 0);
- INIT_NONZERO_SET_SLOTS(so);
- }
-
- so->lookup = set_lookkey_string;
- so->weakreflist = NULL;
-
- if (iterable != NULL) {
- if (set_update_internal(so, iterable) == -1) {
- Py_DECREF(so);
- return NULL;
- }
- }
-
- return (PyObject *)so;
-}
-
-/* The empty frozenset is a singleton */
-static PyObject *emptyfrozenset = NULL;
-
-static PyObject *
-frozenset_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *iterable = NULL, *result;
-
- if (type == &PyFrozenSet_Type && !_PyArg_NoKeywords("frozenset()", kwds))
- return NULL;
-
- if (!PyArg_UnpackTuple(args, type->tp_name, 0, 1, &iterable))
- return NULL;
-
- if (type != &PyFrozenSet_Type)
- return make_new_set(type, iterable);
-
- if (iterable != NULL) {
- /* frozenset(f) is idempotent */
- if (PyFrozenSet_CheckExact(iterable)) {
- Py_INCREF(iterable);
- return iterable;
- }
- result = make_new_set(type, iterable);
- if (result == NULL || PySet_GET_SIZE(result))
- return result;
- Py_DECREF(result);
- }
- /* The empty frozenset is a singleton */
- if (emptyfrozenset == NULL)
- emptyfrozenset = make_new_set(type, NULL);
- Py_XINCREF(emptyfrozenset);
- return emptyfrozenset;
-}
-
-void
-PySet_Fini(void)
-{
- PySetObject *so;
-
- while (num_free_sets) {
- num_free_sets--;
- so = free_sets[num_free_sets];
- PyObject_GC_Del(so);
- }
- Py_CLEAR(dummy);
- Py_CLEAR(emptyfrozenset);
-}
-
-static PyObject *
-set_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- if (type == &PySet_Type && !_PyArg_NoKeywords("set()", kwds))
- return NULL;
-
- return make_new_set(type, NULL);
-}
-
-/* set_swap_bodies() switches the contents of any two sets by moving their
- internal data pointers and, if needed, copying the internal smalltables.
- Semantically equivalent to:
-
- t=set(a); a.clear(); a.update(b); b.clear(); b.update(t); del t
-
- The function always succeeds and it leaves both objects in a stable state.
- Useful for creating temporary frozensets from sets for membership testing
- in __contains__(), discard(), and remove(). Also useful for operations
- that update in-place (by allowing an intermediate result to be swapped
- into one of the original inputs).
-*/
-
-static void
-set_swap_bodies(PySetObject *a, PySetObject *b)
-{
- Py_ssize_t t;
- setentry *u;
- setentry *(*f)(PySetObject *so, PyObject *key, long hash);
- setentry tab[PySet_MINSIZE];
- long h;
-
- t = a->fill; a->fill = b->fill; b->fill = t;
- t = a->used; a->used = b->used; b->used = t;
- t = a->mask; a->mask = b->mask; b->mask = t;
-
- u = a->table;
- if (a->table == a->smalltable)
- u = b->smalltable;
- a->table = b->table;
- if (b->table == b->smalltable)
- a->table = a->smalltable;
- b->table = u;
-
- f = a->lookup; a->lookup = b->lookup; b->lookup = f;
-
- if (a->table == a->smalltable || b->table == b->smalltable) {
- memcpy(tab, a->smalltable, sizeof(tab));
- memcpy(a->smalltable, b->smalltable, sizeof(tab));
- memcpy(b->smalltable, tab, sizeof(tab));
- }
-
- if (PyType_IsSubtype(a->ob_type, &PyFrozenSet_Type) &&
- PyType_IsSubtype(b->ob_type, &PyFrozenSet_Type)) {
- h = a->hash; a->hash = b->hash; b->hash = h;
- } else {
- a->hash = -1;
- b->hash = -1;
- }
-}
-
-static PyObject *
-set_copy(PySetObject *so)
-{
- return make_new_set(so->ob_type, (PyObject *)so);
-}
-
-static PyObject *
-frozenset_copy(PySetObject *so)
-{
- if (PyFrozenSet_CheckExact(so)) {
- Py_INCREF(so);
- return (PyObject *)so;
- }
- return set_copy(so);
-}
-
-PyDoc_STRVAR(copy_doc, "Return a shallow copy of a set.");
-
-static PyObject *
-set_clear(PySetObject *so)
-{
- set_clear_internal(so);
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(clear_doc, "Remove all elements from this set.");
-
-static PyObject *
-set_union(PySetObject *so, PyObject *other)
-{
- PySetObject *result;
-
- result = (PySetObject *)set_copy(so);
- if (result == NULL)
- return NULL;
- if ((PyObject *)so == other)
- return (PyObject *)result;
- if (set_update_internal(result, other) == -1) {
- Py_DECREF(result);
- return NULL;
- }
- return (PyObject *)result;
-}
-
-PyDoc_STRVAR(union_doc,
- "Return the union of two sets as a new set.\n\
-\n\
-(i.e. all elements that are in either set.)");
-
-static PyObject *
-set_or(PySetObject *so, PyObject *other)
-{
- if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return set_union(so, other);
-}
-
-static PyObject *
-set_ior(PySetObject *so, PyObject *other)
-{
- if (!PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- if (set_update_internal(so, other) == -1)
- return NULL;
- Py_INCREF(so);
- return (PyObject *)so;
-}
-
-static PyObject *
-set_intersection(PySetObject *so, PyObject *other)
-{
- PySetObject *result;
- PyObject *key, *it, *tmp;
-
- if ((PyObject *)so == other)
- return set_copy(so);
-
- result = (PySetObject *)make_new_set(so->ob_type, NULL);
- if (result == NULL)
- return NULL;
-
- if (PyAnySet_Check(other)) {
- Py_ssize_t pos = 0;
- setentry *entry;
-
- if (PySet_GET_SIZE(other) > PySet_GET_SIZE(so)) {
- tmp = (PyObject *)so;
- so = (PySetObject *)other;
- other = tmp;
- }
-
- while (set_next((PySetObject *)other, &pos, &entry)) {
- int rv = set_contains_entry(so, entry);
- if (rv == -1) {
- Py_DECREF(result);
- return NULL;
- }
- if (rv) {
- if (set_add_entry(result, entry) == -1) {
- Py_DECREF(result);
- return NULL;
- }
- }
- }
- return (PyObject *)result;
- }
-
- it = PyObject_GetIter(other);
- if (it == NULL) {
- Py_DECREF(result);
- return NULL;
- }
-
- while ((key = PyIter_Next(it)) != NULL) {
- int rv;
- setentry entry;
- long hash = PyObject_Hash(key);
-
- if (hash == -1) {
- Py_DECREF(it);
- Py_DECREF(result);
- Py_DECREF(key);
- return NULL;
- }
- entry.hash = hash;
- entry.key = key;
- rv = set_contains_entry(so, &entry);
- if (rv == -1) {
- Py_DECREF(it);
- Py_DECREF(result);
- Py_DECREF(key);
- return NULL;
- }
- if (rv) {
- if (set_add_entry(result, &entry) == -1) {
- Py_DECREF(it);
- Py_DECREF(result);
- Py_DECREF(key);
- return NULL;
- }
- }
- Py_DECREF(key);
- }
- Py_DECREF(it);
- if (PyErr_Occurred()) {
- Py_DECREF(result);
- return NULL;
- }
- return (PyObject *)result;
-}
-
-PyDoc_STRVAR(intersection_doc,
-"Return the intersection of two sets as a new set.\n\
-\n\
-(i.e. all elements that are in both sets.)");
-
-static PyObject *
-set_intersection_update(PySetObject *so, PyObject *other)
-{
- PyObject *tmp;
-
- tmp = set_intersection(so, other);
- if (tmp == NULL)
- return NULL;
- set_swap_bodies(so, (PySetObject *)tmp);
- Py_DECREF(tmp);
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(intersection_update_doc,
-"Update a set with the intersection of itself and another.");
-
-static PyObject *
-set_and(PySetObject *so, PyObject *other)
-{
- if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return set_intersection(so, other);
-}
-
-static PyObject *
-set_iand(PySetObject *so, PyObject *other)
-{
- PyObject *result;
-
- if (!PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- result = set_intersection_update(so, other);
- if (result == NULL)
- return NULL;
- Py_DECREF(result);
- Py_INCREF(so);
- return (PyObject *)so;
-}
-
-static int
-set_difference_update_internal(PySetObject *so, PyObject *other)
-{
- if ((PyObject *)so == other)
- return set_clear_internal(so);
-
- if (PyAnySet_Check(other)) {
- setentry *entry;
- Py_ssize_t pos = 0;
-
- while (set_next((PySetObject *)other, &pos, &entry))
- if (set_discard_entry(so, entry) == -1)
- return -1;
- } else {
- PyObject *key, *it;
- it = PyObject_GetIter(other);
- if (it == NULL)
- return -1;
-
- while ((key = PyIter_Next(it)) != NULL) {
- if (set_discard_key(so, key) == -1) {
- Py_DECREF(it);
- Py_DECREF(key);
- return -1;
- }
- Py_DECREF(key);
- }
- Py_DECREF(it);
- if (PyErr_Occurred())
- return -1;
- }
- /* If more than 1/5 are dummies, then resize them away. */
- if ((so->fill - so->used) * 5 < so->mask)
- return 0;
- return set_table_resize(so, so->used>50000 ? so->used*2 : so->used*4);
-}
-
-static PyObject *
-set_difference_update(PySetObject *so, PyObject *other)
-{
- if (set_difference_update_internal(so, other) != -1)
- Py_RETURN_NONE;
- return NULL;
-}
-
-PyDoc_STRVAR(difference_update_doc,
-"Remove all elements of another set from this set.");
-
-static PyObject *
-set_difference(PySetObject *so, PyObject *other)
-{
- PyObject *result;
- setentry *entry;
- Py_ssize_t pos = 0;
-
- if (!PyAnySet_Check(other) && !PyDict_CheckExact(other)) {
- result = set_copy(so);
- if (result == NULL)
- return NULL;
- if (set_difference_update_internal((PySetObject *)result, other) != -1)
- return result;
- Py_DECREF(result);
- return NULL;
- }
-
- result = make_new_set(so->ob_type, NULL);
- if (result == NULL)
- return NULL;
-
- if (PyDict_CheckExact(other)) {
- while (set_next(so, &pos, &entry)) {
- setentry entrycopy;
- entrycopy.hash = entry->hash;
- entrycopy.key = entry->key;
- if (!_PyDict_Contains(other, entry->key, entry->hash)) {
- if (set_add_entry((PySetObject *)result, &entrycopy) == -1) {
- Py_DECREF(result);
- return NULL;
- }
- }
- }
- return result;
- }
-
- while (set_next(so, &pos, &entry)) {
- int rv = set_contains_entry((PySetObject *)other, entry);
- if (rv == -1) {
- Py_DECREF(result);
- return NULL;
- }
- if (!rv) {
- if (set_add_entry((PySetObject *)result, entry) == -1) {
- Py_DECREF(result);
- return NULL;
- }
- }
- }
- return result;
-}
-
-PyDoc_STRVAR(difference_doc,
-"Return the difference of two sets as a new set.\n\
-\n\
-(i.e. all elements that are in this set but not the other.)");
-static PyObject *
-set_sub(PySetObject *so, PyObject *other)
-{
- if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return set_difference(so, other);
-}
-
-static PyObject *
-set_isub(PySetObject *so, PyObject *other)
-{
- PyObject *result;
-
- if (!PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- result = set_difference_update(so, other);
- if (result == NULL)
- return NULL;
- Py_DECREF(result);
- Py_INCREF(so);
- return (PyObject *)so;
-}
-
-static PyObject *
-set_symmetric_difference_update(PySetObject *so, PyObject *other)
-{
- PySetObject *otherset;
- PyObject *key;
- Py_ssize_t pos = 0;
- setentry *entry;
-
- if ((PyObject *)so == other)
- return set_clear(so);
-
- if (PyDict_CheckExact(other)) {
- PyObject *value;
- int rv;
- long hash;
- while (_PyDict_Next(other, &pos, &key, &value, &hash)) {
- setentry an_entry;
-
- an_entry.hash = hash;
- an_entry.key = key;
- rv = set_discard_entry(so, &an_entry);
- if (rv == -1)
- return NULL;
- if (rv == DISCARD_NOTFOUND) {
- if (set_add_entry(so, &an_entry) == -1)
- return NULL;
- }
- }
- Py_RETURN_NONE;
- }
-
- if (PyAnySet_Check(other)) {
- Py_INCREF(other);
- otherset = (PySetObject *)other;
- } else {
- otherset = (PySetObject *)make_new_set(so->ob_type, other);
- if (otherset == NULL)
- return NULL;
- }
-
- while (set_next(otherset, &pos, &entry)) {
- int rv = set_discard_entry(so, entry);
- if (rv == -1) {
- Py_DECREF(otherset);
- return NULL;
- }
- if (rv == DISCARD_NOTFOUND) {
- if (set_add_entry(so, entry) == -1) {
- Py_DECREF(otherset);
- return NULL;
- }
- }
- }
- Py_DECREF(otherset);
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(symmetric_difference_update_doc,
-"Update a set with the symmetric difference of itself and another.");
-
-static PyObject *
-set_symmetric_difference(PySetObject *so, PyObject *other)
-{
- PyObject *rv;
- PySetObject *otherset;
-
- otherset = (PySetObject *)make_new_set(so->ob_type, other);
- if (otherset == NULL)
- return NULL;
- rv = set_symmetric_difference_update(otherset, (PyObject *)so);
- if (rv == NULL)
- return NULL;
- Py_DECREF(rv);
- return (PyObject *)otherset;
-}
-
-PyDoc_STRVAR(symmetric_difference_doc,
-"Return the symmetric difference of two sets as a new set.\n\
-\n\
-(i.e. all elements that are in exactly one of the sets.)");
-
-static PyObject *
-set_xor(PySetObject *so, PyObject *other)
-{
- if (!PyAnySet_Check(so) || !PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return set_symmetric_difference(so, other);
-}
-
-static PyObject *
-set_ixor(PySetObject *so, PyObject *other)
-{
- PyObject *result;
-
- if (!PyAnySet_Check(other)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- result = set_symmetric_difference_update(so, other);
- if (result == NULL)
- return NULL;
- Py_DECREF(result);
- Py_INCREF(so);
- return (PyObject *)so;
-}
-
-static PyObject *
-set_issubset(PySetObject *so, PyObject *other)
-{
- setentry *entry;
- Py_ssize_t pos = 0;
-
- if (!PyAnySet_Check(other)) {
- PyObject *tmp, *result;
- tmp = make_new_set(&PySet_Type, other);
- if (tmp == NULL)
- return NULL;
- result = set_issubset(so, tmp);
- Py_DECREF(tmp);
- return result;
- }
- if (PySet_GET_SIZE(so) > PySet_GET_SIZE(other))
- Py_RETURN_FALSE;
-
- while (set_next(so, &pos, &entry)) {
- int rv = set_contains_entry((PySetObject *)other, entry);
- if (rv == -1)
- return NULL;
- if (!rv)
- Py_RETURN_FALSE;
- }
- Py_RETURN_TRUE;
-}
-
-PyDoc_STRVAR(issubset_doc, "Report whether another set contains this set.");
-
-static PyObject *
-set_issuperset(PySetObject *so, PyObject *other)
-{
- PyObject *tmp, *result;
-
- if (!PyAnySet_Check(other)) {
- tmp = make_new_set(&PySet_Type, other);
- if (tmp == NULL)
- return NULL;
- result = set_issuperset(so, tmp);
- Py_DECREF(tmp);
- return result;
- }
- return set_issubset((PySetObject *)other, (PyObject *)so);
-}
-
-PyDoc_STRVAR(issuperset_doc, "Report whether this set contains another set.");
-
-static PyObject *
-set_richcompare(PySetObject *v, PyObject *w, int op)
-{
- PyObject *r1, *r2;
-
- if(!PyAnySet_Check(w)) {
- if (op == Py_EQ)
- Py_RETURN_FALSE;
- if (op == Py_NE)
- Py_RETURN_TRUE;
- PyErr_SetString(PyExc_TypeError, "can only compare to a set");
- return NULL;
- }
- switch (op) {
- case Py_EQ:
- if (PySet_GET_SIZE(v) != PySet_GET_SIZE(w))
- Py_RETURN_FALSE;
- if (v->hash != -1 &&
- ((PySetObject *)w)->hash != -1 &&
- v->hash != ((PySetObject *)w)->hash)
- Py_RETURN_FALSE;
- return set_issubset(v, w);
- case Py_NE:
- r1 = set_richcompare(v, w, Py_EQ);
- if (r1 == NULL)
- return NULL;
- r2 = PyBool_FromLong(PyObject_Not(r1));
- Py_DECREF(r1);
- return r2;
- case Py_LE:
- return set_issubset(v, w);
- case Py_GE:
- return set_issuperset(v, w);
- case Py_LT:
- if (PySet_GET_SIZE(v) >= PySet_GET_SIZE(w))
- Py_RETURN_FALSE;
- return set_issubset(v, w);
- case Py_GT:
- if (PySet_GET_SIZE(v) <= PySet_GET_SIZE(w))
- Py_RETURN_FALSE;
- return set_issuperset(v, w);
- }
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-static int
-set_nocmp(PyObject *self, PyObject *other)
-{
- PyErr_SetString(PyExc_TypeError, "cannot compare sets using cmp()");
- return -1;
-}
-
-static PyObject *
-set_add(PySetObject *so, PyObject *key)
-{
- if (set_add_key(so, key) == -1)
- return NULL;
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(add_doc,
-"Add an element to a set.\n\
-\n\
-This has no effect if the element is already present.");
-
-static int
-set_contains(PySetObject *so, PyObject *key)
-{
- PyObject *tmpkey;
- int rv;
-
- rv = set_contains_key(so, key);
- if (rv == -1) {
- if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
- return -1;
- PyErr_Clear();
- tmpkey = make_new_set(&PyFrozenSet_Type, NULL);
- if (tmpkey == NULL)
- return -1;
- set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
- rv = set_contains(so, tmpkey);
- set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
- Py_DECREF(tmpkey);
- }
- return rv;
-}
-
-static PyObject *
-set_direct_contains(PySetObject *so, PyObject *key)
-{
- long result;
-
- result = set_contains(so, key);
- if (result == -1)
- return NULL;
- return PyBool_FromLong(result);
-}
-
-PyDoc_STRVAR(contains_doc, "x.__contains__(y) <==> y in x.");
-
-static PyObject *
-set_remove(PySetObject *so, PyObject *key)
-{
- PyObject *tmpkey, *result;
- int rv;
-
- rv = set_discard_key(so, key);
- if (rv == -1) {
- if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
- return NULL;
- PyErr_Clear();
- tmpkey = make_new_set(&PyFrozenSet_Type, NULL);
- if (tmpkey == NULL)
- return NULL;
- set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
- result = set_remove(so, tmpkey);
- set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
- Py_DECREF(tmpkey);
- return result;
- } else if (rv == DISCARD_NOTFOUND) {
- set_key_error(key);
- return NULL;
- }
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(remove_doc,
-"Remove an element from a set; it must be a member.\n\
-\n\
-If the element is not a member, raise a KeyError.");
-
-static PyObject *
-set_discard(PySetObject *so, PyObject *key)
-{
- PyObject *tmpkey, *result;
- int rv;
-
- rv = set_discard_key(so, key);
- if (rv == -1) {
- if (!PyAnySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))
- return NULL;
- PyErr_Clear();
- tmpkey = make_new_set(&PyFrozenSet_Type, NULL);
- if (tmpkey == NULL)
- return NULL;
- set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
- result = set_discard(so, tmpkey);
- set_swap_bodies((PySetObject *)tmpkey, (PySetObject *)key);
- Py_DECREF(tmpkey);
- return result;
- }
- Py_RETURN_NONE;
-}
-
-PyDoc_STRVAR(discard_doc,
-"Remove an element from a set if it is a member.\n\
-\n\
-If the element is not a member, do nothing.");
-
-static PyObject *
-set_reduce(PySetObject *so)
-{
- PyObject *keys=NULL, *args=NULL, *result=NULL, *dict=NULL;
-
- keys = PySequence_List((PyObject *)so);
- if (keys == NULL)
- goto done;
- args = PyTuple_Pack(1, keys);
- if (args == NULL)
- goto done;
- dict = PyObject_GetAttrString((PyObject *)so, "__dict__");
- if (dict == NULL) {
- PyErr_Clear();
- dict = Py_None;
- Py_INCREF(dict);
- }
- result = PyTuple_Pack(3, so->ob_type, args, dict);
-done:
- Py_XDECREF(args);
- Py_XDECREF(keys);
- Py_XDECREF(dict);
- return result;
-}
-
-PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
-
-static int
-set_init(PySetObject *self, PyObject *args, PyObject *kwds)
-{
- PyObject *iterable = NULL;
-
- if (!PyAnySet_Check(self))
- return -1;
- if (!PyArg_UnpackTuple(args, self->ob_type->tp_name, 0, 1, &iterable))
- return -1;
- set_clear_internal(self);
- self->hash = -1;
- if (iterable == NULL)
- return 0;
- return set_update_internal(self, iterable);
-}
-
-static PySequenceMethods set_as_sequence = {
- set_len, /* sq_length */
- 0, /* sq_concat */
- 0, /* sq_repeat */
- 0, /* sq_item */
- 0, /* sq_slice */
- 0, /* sq_ass_item */
- 0, /* sq_ass_slice */
- (objobjproc)set_contains, /* sq_contains */
-};
-
-/* set object ********************************************************/
-
-#ifdef Py_DEBUG
-static PyObject *test_c_api(PySetObject *so);
-
-PyDoc_STRVAR(test_c_api_doc, "Exercises C API. Returns True.\n\
-All is well if assertions don't fail.");
-#endif
-
-static PyMethodDef set_methods[] = {
- {"add", (PyCFunction)set_add, METH_O,
- add_doc},
- {"clear", (PyCFunction)set_clear, METH_NOARGS,
- clear_doc},
- {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST,
- contains_doc},
- {"copy", (PyCFunction)set_copy, METH_NOARGS,
- copy_doc},
- {"discard", (PyCFunction)set_discard, METH_O,
- discard_doc},
- {"difference", (PyCFunction)set_difference, METH_O,
- difference_doc},
- {"difference_update", (PyCFunction)set_difference_update, METH_O,
- difference_update_doc},
- {"intersection",(PyCFunction)set_intersection, METH_O,
- intersection_doc},
- {"intersection_update",(PyCFunction)set_intersection_update, METH_O,
- intersection_update_doc},
- {"issubset", (PyCFunction)set_issubset, METH_O,
- issubset_doc},
- {"issuperset", (PyCFunction)set_issuperset, METH_O,
- issuperset_doc},
- {"pop", (PyCFunction)set_pop, METH_NOARGS,
- pop_doc},
- {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS,
- reduce_doc},
- {"remove", (PyCFunction)set_remove, METH_O,
- remove_doc},
- {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,
- symmetric_difference_doc},
- {"symmetric_difference_update",(PyCFunction)set_symmetric_difference_update, METH_O,
- symmetric_difference_update_doc},
-#ifdef Py_DEBUG
- {"test_c_api", (PyCFunction)test_c_api, METH_NOARGS,
- test_c_api_doc},
-#endif
- {"union", (PyCFunction)set_union, METH_O,
- union_doc},
- {"update", (PyCFunction)set_update, METH_O,
- update_doc},
- {NULL, NULL} /* sentinel */
-};
-
-static PyNumberMethods set_as_number = {
- 0, /*nb_add*/
- (binaryfunc)set_sub, /*nb_subtract*/
- 0, /*nb_multiply*/
- 0, /*nb_divide*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- 0, /*nb_negative*/
- 0, /*nb_positive*/
- 0, /*nb_absolute*/
- 0, /*nb_nonzero*/
- 0, /*nb_invert*/
- 0, /*nb_lshift*/
- 0, /*nb_rshift*/
- (binaryfunc)set_and, /*nb_and*/
- (binaryfunc)set_xor, /*nb_xor*/
- (binaryfunc)set_or, /*nb_or*/
- 0, /*nb_coerce*/
- 0, /*nb_int*/
- 0, /*nb_long*/
- 0, /*nb_float*/
- 0, /*nb_oct*/
- 0, /*nb_hex*/
- 0, /*nb_inplace_add*/
- (binaryfunc)set_isub, /*nb_inplace_subtract*/
- 0, /*nb_inplace_multiply*/
- 0, /*nb_inplace_divide*/
- 0, /*nb_inplace_remainder*/
- 0, /*nb_inplace_power*/
- 0, /*nb_inplace_lshift*/
- 0, /*nb_inplace_rshift*/
- (binaryfunc)set_iand, /*nb_inplace_and*/
- (binaryfunc)set_ixor, /*nb_inplace_xor*/
- (binaryfunc)set_ior, /*nb_inplace_or*/
-};
-
-PyDoc_STRVAR(set_doc,
-"set(iterable) --> set object\n\
-\n\
-Build an unordered collection of unique elements.");
-
-PyTypeObject PySet_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "set", /* tp_name */
- sizeof(PySetObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)set_dealloc, /* tp_dealloc */
- (printfunc)set_tp_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- set_nocmp, /* tp_compare */
- (reprfunc)set_repr, /* tp_repr */
- &set_as_number, /* tp_as_number */
- &set_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- set_nohash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- set_doc, /* tp_doc */
- (traverseproc)set_traverse, /* tp_traverse */
- (inquiry)set_clear_internal, /* tp_clear */
- (richcmpfunc)set_richcompare, /* tp_richcompare */
- offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
- (getiterfunc)set_iter, /* tp_iter */
- 0, /* tp_iternext */
- set_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)set_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- set_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-/* frozenset object ********************************************************/
-
-
-static PyMethodDef frozenset_methods[] = {
- {"__contains__",(PyCFunction)set_direct_contains, METH_O | METH_COEXIST,
- contains_doc},
- {"copy", (PyCFunction)frozenset_copy, METH_NOARGS,
- copy_doc},
- {"difference", (PyCFunction)set_difference, METH_O,
- difference_doc},
- {"intersection",(PyCFunction)set_intersection, METH_O,
- intersection_doc},
- {"issubset", (PyCFunction)set_issubset, METH_O,
- issubset_doc},
- {"issuperset", (PyCFunction)set_issuperset, METH_O,
- issuperset_doc},
- {"__reduce__", (PyCFunction)set_reduce, METH_NOARGS,
- reduce_doc},
- {"symmetric_difference",(PyCFunction)set_symmetric_difference, METH_O,
- symmetric_difference_doc},
- {"union", (PyCFunction)set_union, METH_O,
- union_doc},
- {NULL, NULL} /* sentinel */
-};
-
-static PyNumberMethods frozenset_as_number = {
- 0, /*nb_add*/
- (binaryfunc)set_sub, /*nb_subtract*/
- 0, /*nb_multiply*/
- 0, /*nb_divide*/
- 0, /*nb_remainder*/
- 0, /*nb_divmod*/
- 0, /*nb_power*/
- 0, /*nb_negative*/
- 0, /*nb_positive*/
- 0, /*nb_absolute*/
- 0, /*nb_nonzero*/
- 0, /*nb_invert*/
- 0, /*nb_lshift*/
- 0, /*nb_rshift*/
- (binaryfunc)set_and, /*nb_and*/
- (binaryfunc)set_xor, /*nb_xor*/
- (binaryfunc)set_or, /*nb_or*/
-};
-
-PyDoc_STRVAR(frozenset_doc,
-"frozenset(iterable) --> frozenset object\n\
-\n\
-Build an immutable unordered collection of unique elements.");
-
-PyTypeObject PyFrozenSet_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "frozenset", /* tp_name */
- sizeof(PySetObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)set_dealloc, /* tp_dealloc */
- (printfunc)set_tp_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- set_nocmp, /* tp_compare */
- (reprfunc)set_repr, /* tp_repr */
- &frozenset_as_number, /* tp_as_number */
- &set_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- frozenset_hash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- frozenset_doc, /* tp_doc */
- (traverseproc)set_traverse, /* tp_traverse */
- (inquiry)set_clear_internal, /* tp_clear */
- (richcmpfunc)set_richcompare, /* tp_richcompare */
- offsetof(PySetObject, weakreflist), /* tp_weaklistoffset */
- (getiterfunc)set_iter, /* tp_iter */
- 0, /* tp_iternext */
- frozenset_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- frozenset_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-
-/***** C API functions *************************************************/
-
-PyObject *
-PySet_New(PyObject *iterable)
-{
- return make_new_set(&PySet_Type, iterable);
-}
-
-PyObject *
-PyFrozenSet_New(PyObject *iterable)
-{
- PyObject *args, *result;
-
- if (iterable == NULL)
- args = PyTuple_New(0);
- else
- args = PyTuple_Pack(1, iterable);
- if (args == NULL)
- return NULL;
- result = frozenset_new(&PyFrozenSet_Type, args, NULL);
- Py_DECREF(args);
- return result;
-}
-
-Py_ssize_t
-PySet_Size(PyObject *anyset)
-{
- if (!PyAnySet_Check(anyset)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return PySet_GET_SIZE(anyset);
-}
-
-int
-PySet_Clear(PyObject *set)
-{
- if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return set_clear_internal((PySetObject *)set);
-}
-
-int
-PySet_Contains(PyObject *anyset, PyObject *key)
-{
- if (!PyAnySet_Check(anyset)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return set_contains_key((PySetObject *)anyset, key);
-}
-
-int
-PySet_Discard(PyObject *set, PyObject *key)
-{
- if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return set_discard_key((PySetObject *)set, key);
-}
-
-int
-PySet_Add(PyObject *set, PyObject *key)
-{
- if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return set_add_key((PySetObject *)set, key);
-}
-
-int
-_PySet_Next(PyObject *set, Py_ssize_t *pos, PyObject **key)
-{
- setentry *entry_ptr;
-
- if (!PyAnySet_Check(set)) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (set_next((PySetObject *)set, pos, &entry_ptr) == 0)
- return 0;
- *key = entry_ptr->key;
- return 1;
-}
-
-int
-_PySet_NextEntry(PyObject *set, Py_ssize_t *pos, PyObject **key, long *hash)
-{
- setentry *entry;
-
- if (!PyAnySet_Check(set)) {
- PyErr_BadInternalCall();
- return -1;
- }
- if (set_next((PySetObject *)set, pos, &entry) == 0)
- return 0;
- *key = entry->key;
- *hash = entry->hash;
- return 1;
-}
-
-PyObject *
-PySet_Pop(PyObject *set)
-{
- if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return set_pop((PySetObject *)set);
-}
-
-int
-_PySet_Update(PyObject *set, PyObject *iterable)
-{
- if (!PyType_IsSubtype(set->ob_type, &PySet_Type)) {
- PyErr_BadInternalCall();
- return -1;
- }
- return set_update_internal((PySetObject *)set, iterable);
-}
-
-#ifdef Py_DEBUG
-
-/* Test code to be called with any three element set.
- Returns True and original set is restored. */
-
-#define assertRaises(call_return_value, exception) \
- do { \
- assert(call_return_value); \
- assert(PyErr_ExceptionMatches(exception)); \
- PyErr_Clear(); \
- } while(0)
-
-static PyObject *
-test_c_api(PySetObject *so)
-{
- Py_ssize_t count;
- char *s;
- Py_ssize_t i;
- PyObject *elem, *dup, *t, *f, *dup2;
- PyObject *ob = (PyObject *)so;
-
- /* Verify preconditions and exercise type/size checks */
- assert(PyAnySet_Check(ob));
- assert(PyAnySet_CheckExact(ob));
- assert(!PyFrozenSet_CheckExact(ob));
- assert(PySet_Size(ob) == 3);
- assert(PySet_GET_SIZE(ob) == 3);
-
- /* Raise TypeError for non-iterable constructor arguments */
- assertRaises(PySet_New(Py_None) == NULL, PyExc_TypeError);
- assertRaises(PyFrozenSet_New(Py_None) == NULL, PyExc_TypeError);
-
- /* Raise TypeError for unhashable key */
- dup = PySet_New(ob);
- assertRaises(PySet_Discard(ob, dup) == -1, PyExc_TypeError);
- assertRaises(PySet_Contains(ob, dup) == -1, PyExc_TypeError);
- assertRaises(PySet_Add(ob, dup) == -1, PyExc_TypeError);
-
- /* Exercise successful pop, contains, add, and discard */
- elem = PySet_Pop(ob);
- assert(PySet_Contains(ob, elem) == 0);
- assert(PySet_GET_SIZE(ob) == 2);
- assert(PySet_Add(ob, elem) == 0);
- assert(PySet_Contains(ob, elem) == 1);
- assert(PySet_GET_SIZE(ob) == 3);
- assert(PySet_Discard(ob, elem) == 1);
- assert(PySet_GET_SIZE(ob) == 2);
- assert(PySet_Discard(ob, elem) == 0);
- assert(PySet_GET_SIZE(ob) == 2);
-
- /* Exercise clear */
- dup2 = PySet_New(dup);
- assert(PySet_Clear(dup2) == 0);
- assert(PySet_Size(dup2) == 0);
- Py_DECREF(dup2);
-
- /* Raise SystemError on clear or update of frozen set */
- f = PyFrozenSet_New(dup);
- assertRaises(PySet_Clear(f) == -1, PyExc_SystemError);
- assertRaises(_PySet_Update(f, dup) == -1, PyExc_SystemError);
- Py_DECREF(f);
-
- /* Exercise direct iteration */
- i = 0, count = 0;
- while (_PySet_Next((PyObject *)dup, &i, &elem)) {
- s = PyString_AsString(elem);
- assert(s && (s[0] == 'a' || s[0] == 'b' || s[0] == 'c'));
- count++;
- }
- assert(count == 3);
-
- /* Exercise updates */
- dup2 = PySet_New(NULL);
- assert(_PySet_Update(dup2, dup) == 0);
- assert(PySet_Size(dup2) == 3);
- assert(_PySet_Update(dup2, dup) == 0);
- assert(PySet_Size(dup2) == 3);
- Py_DECREF(dup2);
-
- /* Raise SystemError when self argument is not a set or frozenset. */
- t = PyTuple_New(0);
- assertRaises(PySet_Size(t) == -1, PyExc_SystemError);
- assertRaises(PySet_Contains(t, elem) == -1, PyExc_SystemError);
- Py_DECREF(t);
-
- /* Raise SystemError when self argument is not a set. */
- f = PyFrozenSet_New(dup);
- assert(PySet_Size(f) == 3);
- assert(PyFrozenSet_CheckExact(f));
- assertRaises(PySet_Add(f, elem) == -1, PyExc_SystemError);
- assertRaises(PySet_Discard(f, elem) == -1, PyExc_SystemError);
- assertRaises(PySet_Pop(f) == NULL, PyExc_SystemError);
- Py_DECREF(f);
-
- /* Raise KeyError when popping from an empty set */
- assert(PyNumber_InPlaceSubtract(ob, ob) == ob);
- Py_DECREF(ob);
- assert(PySet_GET_SIZE(ob) == 0);
- assertRaises(PySet_Pop(ob) == NULL, PyExc_KeyError);
-
- /* Restore the set from the copy using the PyNumber API */
- assert(PyNumber_InPlaceOr(ob, dup) == ob);
- Py_DECREF(ob);
-
- /* Verify constructors accept NULL arguments */
- f = PySet_New(NULL);
- assert(f != NULL);
- assert(PySet_GET_SIZE(f) == 0);
- Py_DECREF(f);
- f = PyFrozenSet_New(NULL);
- assert(f != NULL);
- assert(PyFrozenSet_CheckExact(f));
- assert(PySet_GET_SIZE(f) == 0);
- Py_DECREF(f);
-
- Py_DECREF(elem);
- Py_DECREF(dup);
- Py_RETURN_TRUE;
-}
-
-#undef assertRaises
-
-#endif
diff --git a/sys/src/cmd/python/Objects/sliceobject.c b/sys/src/cmd/python/Objects/sliceobject.c
deleted file mode 100644
index d8a24653a..000000000
--- a/sys/src/cmd/python/Objects/sliceobject.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
-Written by Jim Hugunin and Chris Chase.
-
-This includes both the singular ellipsis object and slice objects.
-
-Guido, feel free to do whatever you want in the way of copyrights
-for this file.
-*/
-
-/*
-Py_Ellipsis encodes the '...' rubber index token. It is similar to
-the Py_NoneStruct in that there is no way to create other objects of
-this type and there is exactly one in existence.
-*/
-
-#include "Python.h"
-#include "structmember.h"
-
-static PyObject *
-ellipsis_repr(PyObject *op)
-{
- return PyString_FromString("Ellipsis");
-}
-
-static PyTypeObject PyEllipsis_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "ellipsis", /* tp_name */
- 0, /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /*never called*/ /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- ellipsis_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
-};
-
-PyObject _Py_EllipsisObject = {
- PyObject_HEAD_INIT(&PyEllipsis_Type)
-};
-
-
-/* Slice object implementation
-
- start, stop, and step are python objects with None indicating no
- index is present.
-*/
-
-PyObject *
-PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
-{
- PySliceObject *obj = PyObject_New(PySliceObject, &PySlice_Type);
-
- if (obj == NULL)
- return NULL;
-
- if (step == NULL) step = Py_None;
- Py_INCREF(step);
- if (start == NULL) start = Py_None;
- Py_INCREF(start);
- if (stop == NULL) stop = Py_None;
- Py_INCREF(stop);
-
- obj->step = step;
- obj->start = start;
- obj->stop = stop;
-
- return (PyObject *) obj;
-}
-
-PyObject *
-_PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
-{
- PyObject *start, *end, *slice;
- start = PyInt_FromSsize_t(istart);
- if (!start)
- return NULL;
- end = PyInt_FromSsize_t(istop);
- if (!end) {
- Py_DECREF(start);
- return NULL;
- }
-
- slice = PySlice_New(start, end, NULL);
- Py_DECREF(start);
- Py_DECREF(end);
- return slice;
-}
-
-int
-PySlice_GetIndices(PySliceObject *r, Py_ssize_t length,
- Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
-{
- /* XXX support long ints */
- if (r->step == Py_None) {
- *step = 1;
- } else {
- if (!PyInt_Check(r->step) && !PyLong_Check(r->step)) return -1;
- *step = PyInt_AsSsize_t(r->step);
- }
- if (r->start == Py_None) {
- *start = *step < 0 ? length-1 : 0;
- } else {
- if (!PyInt_Check(r->start) && !PyLong_Check(r->step)) return -1;
- *start = PyInt_AsSsize_t(r->start);
- if (*start < 0) *start += length;
- }
- if (r->stop == Py_None) {
- *stop = *step < 0 ? -1 : length;
- } else {
- if (!PyInt_Check(r->stop) && !PyLong_Check(r->step)) return -1;
- *stop = PyInt_AsSsize_t(r->stop);
- if (*stop < 0) *stop += length;
- }
- if (*stop > length) return -1;
- if (*start >= length) return -1;
- if (*step == 0) return -1;
- return 0;
-}
-
-int
-PySlice_GetIndicesEx(PySliceObject *r, Py_ssize_t length,
- Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step, Py_ssize_t *slicelength)
-{
- /* this is harder to get right than you might think */
-
- Py_ssize_t defstart, defstop;
-
- if (r->step == Py_None) {
- *step = 1;
- }
- else {
- if (!_PyEval_SliceIndex(r->step, step)) return -1;
- if (*step == 0) {
- PyErr_SetString(PyExc_ValueError,
- "slice step cannot be zero");
- return -1;
- }
- }
-
- defstart = *step < 0 ? length-1 : 0;
- defstop = *step < 0 ? -1 : length;
-
- if (r->start == Py_None) {
- *start = defstart;
- }
- else {
- if (!_PyEval_SliceIndex(r->start, start)) return -1;
- if (*start < 0) *start += length;
- if (*start < 0) *start = (*step < 0) ? -1 : 0;
- if (*start >= length)
- *start = (*step < 0) ? length - 1 : length;
- }
-
- if (r->stop == Py_None) {
- *stop = defstop;
- }
- else {
- if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
- if (*stop < 0) *stop += length;
- if (*stop < 0) *stop = -1;
- if (*stop > length) *stop = length;
- }
-
- if ((*step < 0 && *stop >= *start)
- || (*step > 0 && *start >= *stop)) {
- *slicelength = 0;
- }
- else if (*step < 0) {
- *slicelength = (*stop-*start+1)/(*step)+1;
- }
- else {
- *slicelength = (*stop-*start-1)/(*step)+1;
- }
-
- return 0;
-}
-
-static PyObject *
-slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
-{
- PyObject *start, *stop, *step;
-
- start = stop = step = NULL;
-
- if (!_PyArg_NoKeywords("slice()", kw))
- return NULL;
-
- if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
- return NULL;
-
- /* This swapping of stop and start is to maintain similarity with
- range(). */
- if (stop == NULL) {
- stop = start;
- start = NULL;
- }
- return PySlice_New(start, stop, step);
-}
-
-PyDoc_STRVAR(slice_doc,
-"slice([start,] stop[, step])\n\
-\n\
-Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).");
-
-static void
-slice_dealloc(PySliceObject *r)
-{
- Py_DECREF(r->step);
- Py_DECREF(r->start);
- Py_DECREF(r->stop);
- PyObject_Del(r);
-}
-
-static PyObject *
-slice_repr(PySliceObject *r)
-{
- PyObject *s, *comma;
-
- s = PyString_FromString("slice(");
- comma = PyString_FromString(", ");
- PyString_ConcatAndDel(&s, PyObject_Repr(r->start));
- PyString_Concat(&s, comma);
- PyString_ConcatAndDel(&s, PyObject_Repr(r->stop));
- PyString_Concat(&s, comma);
- PyString_ConcatAndDel(&s, PyObject_Repr(r->step));
- PyString_ConcatAndDel(&s, PyString_FromString(")"));
- Py_DECREF(comma);
- return s;
-}
-
-static PyMemberDef slice_members[] = {
- {"start", T_OBJECT, offsetof(PySliceObject, start), READONLY},
- {"stop", T_OBJECT, offsetof(PySliceObject, stop), READONLY},
- {"step", T_OBJECT, offsetof(PySliceObject, step), READONLY},
- {0}
-};
-
-static PyObject*
-slice_indices(PySliceObject* self, PyObject* len)
-{
- Py_ssize_t ilen, start, stop, step, slicelength;
-
- ilen = PyNumber_AsSsize_t(len, PyExc_OverflowError);
-
- if (ilen == -1 && PyErr_Occurred()) {
- return NULL;
- }
-
- if (PySlice_GetIndicesEx(self, ilen, &start, &stop,
- &step, &slicelength) < 0) {
- return NULL;
- }
-
- return Py_BuildValue("(nnn)", start, stop, step);
-}
-
-PyDoc_STRVAR(slice_indices_doc,
-"S.indices(len) -> (start, stop, stride)\n\
-\n\
-Assuming a sequence of length len, calculate the start and stop\n\
-indices, and the stride length of the extended slice described by\n\
-S. Out of bounds indices are clipped in a manner consistent with the\n\
-handling of normal slices.");
-
-static PyMethodDef slice_methods[] = {
- {"indices", (PyCFunction)slice_indices,
- METH_O, slice_indices_doc},
- {NULL, NULL}
-};
-
-static int
-slice_compare(PySliceObject *v, PySliceObject *w)
-{
- int result = 0;
-
- if (v == w)
- return 0;
-
- if (PyObject_Cmp(v->start, w->start, &result) < 0)
- return -2;
- if (result != 0)
- return result;
- if (PyObject_Cmp(v->stop, w->stop, &result) < 0)
- return -2;
- if (result != 0)
- return result;
- if (PyObject_Cmp(v->step, w->step, &result) < 0)
- return -2;
- return result;
-}
-
-static long
-slice_hash(PySliceObject *v)
-{
- PyErr_SetString(PyExc_TypeError, "unhashable type");
- return -1L;
-}
-
-PyTypeObject PySlice_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* Number of items for varobject */
- "slice", /* Name of this type */
- sizeof(PySliceObject), /* Basic object size */
- 0, /* Item size for varobject */
- (destructor)slice_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- (cmpfunc)slice_compare, /* tp_compare */
- (reprfunc)slice_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)slice_hash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- slice_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- slice_methods, /* tp_methods */
- slice_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- slice_new, /* tp_new */
-};
diff --git a/sys/src/cmd/python/Objects/stringlib/README.txt b/sys/src/cmd/python/Objects/stringlib/README.txt
deleted file mode 100644
index 82a877465..000000000
--- a/sys/src/cmd/python/Objects/stringlib/README.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-bits shared by the stringobject and unicodeobject implementations (and
-possibly other modules, in a not too distant future).
-
-the stuff in here is included into relevant places; see the individual
-source files for details.
-
---------------------------------------------------------------------
-the following defines used by the different modules:
-
-STRINGLIB_CHAR
-
- the type used to hold a character (char or Py_UNICODE)
-
-STRINGLIB_EMPTY
-
- a PyObject representing the empty string
-
-int STRINGLIB_CMP(STRINGLIB_CHAR*, STRINGLIB_CHAR*, Py_ssize_t)
-
- compares two strings. returns 0 if they match, and non-zero if not.
-
-Py_ssize_t STRINGLIB_LEN(PyObject*)
-
- returns the length of the given string object (which must be of the
- right type)
-
-PyObject* STRINGLIB_NEW(STRINGLIB_CHAR*, Py_ssize_t)
-
- creates a new string object
-
-STRINGLIB_CHAR* STRINGLIB_STR(PyObject*)
-
- returns the pointer to the character data for the given string
- object (which must be of the right type)
diff --git a/sys/src/cmd/python/Objects/stringlib/count.h b/sys/src/cmd/python/Objects/stringlib/count.h
deleted file mode 100644
index 367a15c51..000000000
--- a/sys/src/cmd/python/Objects/stringlib/count.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* stringlib: count implementation */
-
-#ifndef STRINGLIB_COUNT_H
-#define STRINGLIB_COUNT_H
-
-#ifndef STRINGLIB_FASTSEARCH_H
-#error must include "stringlib/fastsearch.h" before including this module
-#endif
-
-Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_count(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
- const STRINGLIB_CHAR* sub, Py_ssize_t sub_len)
-{
- Py_ssize_t count;
-
- if (sub_len == 0) {
- if (str_len < 0)
- return 0; /* start > len(str) */
- return str_len + 1;
- }
-
- count = fastsearch(str, str_len, sub, sub_len, FAST_COUNT);
-
- if (count < 0)
- count = 0; /* no match */
-
- return count;
-}
-
-#endif
-
-/*
-Local variables:
-c-basic-offset: 4
-indent-tabs-mode: nil
-End:
-*/
diff --git a/sys/src/cmd/python/Objects/stringlib/fastsearch.h b/sys/src/cmd/python/Objects/stringlib/fastsearch.h
deleted file mode 100644
index 8f79c360d..000000000
--- a/sys/src/cmd/python/Objects/stringlib/fastsearch.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/* stringlib: fastsearch implementation */
-
-#ifndef STRINGLIB_FASTSEARCH_H
-#define STRINGLIB_FASTSEARCH_H
-
-/* fast search/count implementation, based on a mix between boyer-
- moore and horspool, with a few more bells and whistles on the top.
- for some more background, see: http://effbot.org/stringlib */
-
-/* note: fastsearch may access s[n], which isn't a problem when using
- Python's ordinary string types, but may cause problems if you're
- using this code in other contexts. also, the count mode returns -1
- if there cannot possible be a match in the target string, and 0 if
- it has actually checked for matches, but didn't find any. callers
- beware! */
-
-#define FAST_COUNT 0
-#define FAST_SEARCH 1
-
-Py_LOCAL_INLINE(Py_ssize_t)
-fastsearch(const STRINGLIB_CHAR* s, Py_ssize_t n,
- const STRINGLIB_CHAR* p, Py_ssize_t m,
- int mode)
-{
- long mask;
- Py_ssize_t skip, count = 0;
- Py_ssize_t i, j, mlast, w;
-
- w = n - m;
-
- if (w < 0)
- return -1;
-
- /* look for special cases */
- if (m <= 1) {
- if (m <= 0)
- return -1;
- /* use special case for 1-character strings */
- if (mode == FAST_COUNT) {
- for (i = 0; i < n; i++)
- if (s[i] == p[0])
- count++;
- return count;
- } else {
- for (i = 0; i < n; i++)
- if (s[i] == p[0])
- return i;
- }
- return -1;
- }
-
- mlast = m - 1;
-
- /* create compressed boyer-moore delta 1 table */
- skip = mlast - 1;
- /* process pattern[:-1] */
- for (mask = i = 0; i < mlast; i++) {
- mask |= (1 << (p[i] & 0x1F));
- if (p[i] == p[mlast])
- skip = mlast - i - 1;
- }
- /* process pattern[-1] outside the loop */
- mask |= (1 << (p[mlast] & 0x1F));
-
- for (i = 0; i <= w; i++) {
- /* note: using mlast in the skip path slows things down on x86 */
- if (s[i+m-1] == p[m-1]) {
- /* candidate match */
- for (j = 0; j < mlast; j++)
- if (s[i+j] != p[j])
- break;
- if (j == mlast) {
- /* got a match! */
- if (mode != FAST_COUNT)
- return i;
- count++;
- i = i + mlast;
- continue;
- }
- /* miss: check if next character is part of pattern */
- if (!(mask & (1 << (s[i+m] & 0x1F))))
- i = i + m;
- else
- i = i + skip;
- } else {
- /* skip: check if next character is part of pattern */
- if (!(mask & (1 << (s[i+m] & 0x1F))))
- i = i + m;
- }
- }
-
- if (mode != FAST_COUNT)
- return -1;
- return count;
-}
-
-#endif
-
-/*
-Local variables:
-c-basic-offset: 4
-indent-tabs-mode: nil
-End:
-*/
diff --git a/sys/src/cmd/python/Objects/stringlib/find.h b/sys/src/cmd/python/Objects/stringlib/find.h
deleted file mode 100644
index 4cdbb096d..000000000
--- a/sys/src/cmd/python/Objects/stringlib/find.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* stringlib: find/index implementation */
-
-#ifndef STRINGLIB_FIND_H
-#define STRINGLIB_FIND_H
-
-#ifndef STRINGLIB_FASTSEARCH_H
-#error must include "stringlib/fastsearch.h" before including this module
-#endif
-
-Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
- const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
- Py_ssize_t offset)
-{
- Py_ssize_t pos;
-
- if (sub_len == 0) {
- if (str_len < 0)
- return -1;
- return offset;
- }
-
- pos = fastsearch(str, str_len, sub, sub_len, FAST_SEARCH);
-
- if (pos >= 0)
- pos += offset;
-
- return pos;
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
- const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
- Py_ssize_t offset)
-{
- /* XXX - create reversefastsearch helper! */
- if (sub_len == 0) {
- if (str_len < 0)
- return -1;
- return str_len + offset;
- } else {
- Py_ssize_t j, pos = -1;
- for (j = str_len - sub_len; j >= 0; --j)
- if (STRINGLIB_CMP(str+j, sub, sub_len) == 0) {
- pos = j + offset;
- break;
- }
- return pos;
- }
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
- const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
- Py_ssize_t start, Py_ssize_t end)
-{
- if (start < 0)
- start += str_len;
- if (start < 0)
- start = 0;
- if (end > str_len)
- end = str_len;
- if (end < 0)
- end += str_len;
- if (end < 0)
- end = 0;
-
- return stringlib_find(
- str + start, end - start,
- sub, sub_len, start
- );
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
- const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
- Py_ssize_t start, Py_ssize_t end)
-{
- if (start < 0)
- start += str_len;
- if (start < 0)
- start = 0;
- if (end > str_len)
- end = str_len;
- if (end < 0)
- end += str_len;
- if (end < 0)
- end = 0;
-
- return stringlib_rfind(str + start, end - start, sub, sub_len, start);
-}
-
-#ifdef STRINGLIB_STR
-
-Py_LOCAL_INLINE(int)
-stringlib_contains_obj(PyObject* str, PyObject* sub)
-{
- return stringlib_find(
- STRINGLIB_STR(str), STRINGLIB_LEN(str),
- STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
- ) != -1;
-}
-
-#endif /* STRINGLIB_STR */
-
-#endif /* STRINGLIB_FIND_H */
-
-/*
-Local variables:
-c-basic-offset: 4
-indent-tabs-mode: nil
-End:
-*/
diff --git a/sys/src/cmd/python/Objects/stringlib/partition.h b/sys/src/cmd/python/Objects/stringlib/partition.h
deleted file mode 100644
index 105ba317d..000000000
--- a/sys/src/cmd/python/Objects/stringlib/partition.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* stringlib: partition implementation */
-
-#ifndef STRINGLIB_PARTITION_H
-#define STRINGLIB_PARTITION_H
-
-#ifndef STRINGLIB_FASTSEARCH_H
-#error must include "stringlib/fastsearch.h" before including this module
-#endif
-
-Py_LOCAL_INLINE(PyObject*)
-stringlib_partition(
- PyObject* str_obj, const STRINGLIB_CHAR* str, Py_ssize_t str_len,
- PyObject* sep_obj, const STRINGLIB_CHAR* sep, Py_ssize_t sep_len
- )
-{
- PyObject* out;
- Py_ssize_t pos;
-
- if (sep_len == 0) {
- PyErr_SetString(PyExc_ValueError, "empty separator");
- return NULL;
- }
-
- out = PyTuple_New(3);
- if (!out)
- return NULL;
-
- pos = fastsearch(str, str_len, sep, sep_len, FAST_SEARCH);
-
- if (pos < 0) {
- Py_INCREF(str_obj);
- PyTuple_SET_ITEM(out, 0, (PyObject*) str_obj);
- Py_INCREF(STRINGLIB_EMPTY);
- PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY);
- Py_INCREF(STRINGLIB_EMPTY);
- PyTuple_SET_ITEM(out, 2, (PyObject*) STRINGLIB_EMPTY);
- return out;
- }
-
- PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));
- Py_INCREF(sep_obj);
- PyTuple_SET_ITEM(out, 1, sep_obj);
- pos += sep_len;
- PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));
-
- if (PyErr_Occurred()) {
- Py_DECREF(out);
- return NULL;
- }
-
- return out;
-}
-
-Py_LOCAL_INLINE(PyObject*)
-stringlib_rpartition(
- PyObject* str_obj, const STRINGLIB_CHAR* str, Py_ssize_t str_len,
- PyObject* sep_obj, const STRINGLIB_CHAR* sep, Py_ssize_t sep_len
- )
-{
- PyObject* out;
- Py_ssize_t pos, j;
-
- if (sep_len == 0) {
- PyErr_SetString(PyExc_ValueError, "empty separator");
- return NULL;
- }
-
- out = PyTuple_New(3);
- if (!out)
- return NULL;
-
- /* XXX - create reversefastsearch helper! */
- pos = -1;
- for (j = str_len - sep_len; j >= 0; --j)
- if (STRINGLIB_CMP(str+j, sep, sep_len) == 0) {
- pos = j;
- break;
- }
-
- if (pos < 0) {
- Py_INCREF(STRINGLIB_EMPTY);
- PyTuple_SET_ITEM(out, 0, (PyObject*) STRINGLIB_EMPTY);
- Py_INCREF(STRINGLIB_EMPTY);
- PyTuple_SET_ITEM(out, 1, (PyObject*) STRINGLIB_EMPTY);
- Py_INCREF(str_obj);
- PyTuple_SET_ITEM(out, 2, (PyObject*) str_obj);
- return out;
- }
-
- PyTuple_SET_ITEM(out, 0, STRINGLIB_NEW(str, pos));
- Py_INCREF(sep_obj);
- PyTuple_SET_ITEM(out, 1, sep_obj);
- pos += sep_len;
- PyTuple_SET_ITEM(out, 2, STRINGLIB_NEW(str + pos, str_len - pos));
-
- if (PyErr_Occurred()) {
- Py_DECREF(out);
- return NULL;
- }
-
- return out;
-}
-
-#endif
-
-/*
-Local variables:
-c-basic-offset: 4
-indent-tabs-mode: nil
-End:
-*/
diff --git a/sys/src/cmd/python/Objects/stringobject.c b/sys/src/cmd/python/Objects/stringobject.c
deleted file mode 100644
index 5ae2ca06c..000000000
--- a/sys/src/cmd/python/Objects/stringobject.c
+++ /dev/null
@@ -1,5009 +0,0 @@
-/* String object implementation */
-
-#define PY_SSIZE_T_CLEAN
-
-#include "Python.h"
-
-#include <ctype.h>
-
-#ifdef COUNT_ALLOCS
-int null_strings, one_strings;
-#endif
-
-static PyStringObject *characters[UCHAR_MAX + 1];
-static PyStringObject *nullstring;
-
-/* This dictionary holds all interned strings. Note that references to
- strings in this dictionary are *not* counted in the string's ob_refcnt.
- When the interned string reaches a refcnt of 0 the string deallocation
- function will delete the reference from this dictionary.
-
- Another way to look at this is that to say that the actual reference
- count of a string is: s->ob_refcnt + (s->ob_sstate?2:0)
-*/
-static PyObject *interned;
-
-/*
- For both PyString_FromString() and PyString_FromStringAndSize(), the
- parameter `size' denotes number of characters to allocate, not counting any
- null terminating character.
-
- For PyString_FromString(), the parameter `str' points to a null-terminated
- string containing exactly `size' bytes.
-
- For PyString_FromStringAndSize(), the parameter the parameter `str' is
- either NULL or else points to a string containing at least `size' bytes.
- For PyString_FromStringAndSize(), the string in the `str' parameter does
- not have to be null-terminated. (Therefore it is safe to construct a
- substring by calling `PyString_FromStringAndSize(origstring, substrlen)'.)
- If `str' is NULL then PyString_FromStringAndSize() will allocate `size+1'
- bytes (setting the last byte to the null terminating character) and you can
- fill in the data yourself. If `str' is non-NULL then the resulting
- PyString object must be treated as immutable and you must not fill in nor
- alter the data yourself, since the strings may be shared.
-
- The PyObject member `op->ob_size', which denotes the number of "extra
- items" in a variable-size object, will contain the number of bytes
- allocated for string data, not counting the null terminating character. It
- is therefore equal to the equal to the `size' parameter (for
- PyString_FromStringAndSize()) or the length of the string in the `str'
- parameter (for PyString_FromString()).
-*/
-PyObject *
-PyString_FromStringAndSize(const char *str, Py_ssize_t size)
-{
- register PyStringObject *op;
- assert(size >= 0);
- if (size == 0 && (op = nullstring) != NULL) {
-#ifdef COUNT_ALLOCS
- null_strings++;
-#endif
- Py_INCREF(op);
- return (PyObject *)op;
- }
- if (size == 1 && str != NULL &&
- (op = characters[*str & UCHAR_MAX]) != NULL)
- {
-#ifdef COUNT_ALLOCS
- one_strings++;
-#endif
- Py_INCREF(op);
- return (PyObject *)op;
- }
-
- /* Inline PyObject_NewVar */
- op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
- if (op == NULL)
- return PyErr_NoMemory();
- PyObject_INIT_VAR(op, &PyString_Type, size);
- op->ob_shash = -1;
- op->ob_sstate = SSTATE_NOT_INTERNED;
- if (str != NULL)
- Py_MEMCPY(op->ob_sval, str, size);
- op->ob_sval[size] = '\0';
- /* share short strings */
- if (size == 0) {
- PyObject *t = (PyObject *)op;
- PyString_InternInPlace(&t);
- op = (PyStringObject *)t;
- nullstring = op;
- Py_INCREF(op);
- } else if (size == 1 && str != NULL) {
- PyObject *t = (PyObject *)op;
- PyString_InternInPlace(&t);
- op = (PyStringObject *)t;
- characters[*str & UCHAR_MAX] = op;
- Py_INCREF(op);
- }
- return (PyObject *) op;
-}
-
-PyObject *
-PyString_FromString(const char *str)
-{
- register size_t size;
- register PyStringObject *op;
-
- assert(str != NULL);
- size = strlen(str);
- if (size > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "string is too long for a Python string");
- return NULL;
- }
- if (size == 0 && (op = nullstring) != NULL) {
-#ifdef COUNT_ALLOCS
- null_strings++;
-#endif
- Py_INCREF(op);
- return (PyObject *)op;
- }
- if (size == 1 && (op = characters[*str & UCHAR_MAX]) != NULL) {
-#ifdef COUNT_ALLOCS
- one_strings++;
-#endif
- Py_INCREF(op);
- return (PyObject *)op;
- }
-
- /* Inline PyObject_NewVar */
- op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
- if (op == NULL)
- return PyErr_NoMemory();
- PyObject_INIT_VAR(op, &PyString_Type, size);
- op->ob_shash = -1;
- op->ob_sstate = SSTATE_NOT_INTERNED;
- Py_MEMCPY(op->ob_sval, str, size+1);
- /* share short strings */
- if (size == 0) {
- PyObject *t = (PyObject *)op;
- PyString_InternInPlace(&t);
- op = (PyStringObject *)t;
- nullstring = op;
- Py_INCREF(op);
- } else if (size == 1) {
- PyObject *t = (PyObject *)op;
- PyString_InternInPlace(&t);
- op = (PyStringObject *)t;
- characters[*str & UCHAR_MAX] = op;
- Py_INCREF(op);
- }
- return (PyObject *) op;
-}
-
-PyObject *
-PyString_FromFormatV(const char *format, va_list vargs)
-{
- va_list count;
- Py_ssize_t n = 0;
- const char* f;
- char *s;
- PyObject* string;
-
-#ifdef VA_LIST_IS_ARRAY
- Py_MEMCPY(count, vargs, sizeof(va_list));
-#else
-#ifdef __va_copy
- __va_copy(count, vargs);
-#else
- count = vargs;
-#endif
-#endif
- /* step 1: figure out how large a buffer we need */
- for (f = format; *f; f++) {
- if (*f == '%') {
- const char* p = f;
- while (*++f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
- ;
-
- /* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since
- * they don't affect the amount of space we reserve.
- */
- if ((*f == 'l' || *f == 'z') &&
- (f[1] == 'd' || f[1] == 'u'))
- ++f;
-
- switch (*f) {
- case 'c':
- (void)va_arg(count, int);
- /* fall through... */
- case '%':
- n++;
- break;
- case 'd': case 'u': case 'i': case 'x':
- (void) va_arg(count, int);
- /* 20 bytes is enough to hold a 64-bit
- integer. Decimal takes the most space.
- This isn't enough for octal. */
- n += 20;
- break;
- case 's':
- s = va_arg(count, char*);
- n += strlen(s);
- break;
- case 'p':
- (void) va_arg(count, int);
- /* maximum 64-bit pointer representation:
- * 0xffffffffffffffff
- * so 19 characters is enough.
- * XXX I count 18 -- what's the extra for?
- */
- n += 19;
- break;
- default:
- /* if we stumble upon an unknown
- formatting code, copy the rest of
- the format string to the output
- string. (we cannot just skip the
- code, since there's no way to know
- what's in the argument list) */
- n += strlen(p);
- goto expand;
- }
- } else
- n++;
- }
- expand:
- /* step 2: fill the buffer */
- /* Since we've analyzed how much space we need for the worst case,
- use sprintf directly instead of the slower PyOS_snprintf. */
- string = PyString_FromStringAndSize(NULL, n);
- if (!string)
- return NULL;
-
- s = PyString_AsString(string);
-
- for (f = format; *f; f++) {
- if (*f == '%') {
- const char* p = f++;
- Py_ssize_t i;
- int longflag = 0;
- int size_tflag = 0;
- /* parse the width.precision part (we're only
- interested in the precision value, if any) */
- n = 0;
- while (isdigit(Py_CHARMASK(*f)))
- n = (n*10) + *f++ - '0';
- if (*f == '.') {
- f++;
- n = 0;
- while (isdigit(Py_CHARMASK(*f)))
- n = (n*10) + *f++ - '0';
- }
- while (*f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
- f++;
- /* handle the long flag, but only for %ld and %lu.
- others can be added when necessary. */
- if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) {
- longflag = 1;
- ++f;
- }
- /* handle the size_t flag. */
- if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {
- size_tflag = 1;
- ++f;
- }
-
- switch (*f) {
- case 'c':
- *s++ = va_arg(vargs, int);
- break;
- case 'd':
- if (longflag)
- sprintf(s, "%ld", va_arg(vargs, long));
- else if (size_tflag)
- sprintf(s, "%" PY_FORMAT_SIZE_T "d",
- va_arg(vargs, Py_ssize_t));
- else
- sprintf(s, "%d", va_arg(vargs, int));
- s += strlen(s);
- break;
- case 'u':
- if (longflag)
- sprintf(s, "%lu",
- va_arg(vargs, unsigned long));
- else if (size_tflag)
- sprintf(s, "%" PY_FORMAT_SIZE_T "u",
- va_arg(vargs, size_t));
- else
- sprintf(s, "%u",
- va_arg(vargs, unsigned int));
- s += strlen(s);
- break;
- case 'i':
- sprintf(s, "%i", va_arg(vargs, int));
- s += strlen(s);
- break;
- case 'x':
- sprintf(s, "%x", va_arg(vargs, int));
- s += strlen(s);
- break;
- case 's':
- p = va_arg(vargs, char*);
- i = strlen(p);
- if (n > 0 && i > n)
- i = n;
- Py_MEMCPY(s, p, i);
- s += i;
- break;
- case 'p':
- sprintf(s, "%p", va_arg(vargs, void*));
- /* %p is ill-defined: ensure leading 0x. */
- if (s[1] == 'X')
- s[1] = 'x';
- else if (s[1] != 'x') {
- memmove(s+2, s, strlen(s)+1);
- s[0] = '0';
- s[1] = 'x';
- }
- s += strlen(s);
- break;
- case '%':
- *s++ = '%';
- break;
- default:
- strcpy(s, p);
- s += strlen(s);
- goto end;
- }
- } else
- *s++ = *f;
- }
-
- end:
- _PyString_Resize(&string, s - PyString_AS_STRING(string));
- return string;
-}
-
-PyObject *
-PyString_FromFormat(const char *format, ...)
-{
- PyObject* ret;
- va_list vargs;
-
-#ifdef HAVE_STDARG_PROTOTYPES
- va_start(vargs, format);
-#else
- va_start(vargs);
-#endif
- ret = PyString_FromFormatV(format, vargs);
- va_end(vargs);
- return ret;
-}
-
-
-PyObject *PyString_Decode(const char *s,
- Py_ssize_t size,
- const char *encoding,
- const char *errors)
-{
- PyObject *v, *str;
-
- str = PyString_FromStringAndSize(s, size);
- if (str == NULL)
- return NULL;
- v = PyString_AsDecodedString(str, encoding, errors);
- Py_DECREF(str);
- return v;
-}
-
-PyObject *PyString_AsDecodedObject(PyObject *str,
- const char *encoding,
- const char *errors)
-{
- PyObject *v;
-
- if (!PyString_Check(str)) {
- PyErr_BadArgument();
- goto onError;
- }
-
- if (encoding == NULL) {
-#ifdef Py_USING_UNICODE
- encoding = PyUnicode_GetDefaultEncoding();
-#else
- PyErr_SetString(PyExc_ValueError, "no encoding specified");
- goto onError;
-#endif
- }
-
- /* Decode via the codec registry */
- v = PyCodec_Decode(str, encoding, errors);
- if (v == NULL)
- goto onError;
-
- return v;
-
- onError:
- return NULL;
-}
-
-PyObject *PyString_AsDecodedString(PyObject *str,
- const char *encoding,
- const char *errors)
-{
- PyObject *v;
-
- v = PyString_AsDecodedObject(str, encoding, errors);
- if (v == NULL)
- goto onError;
-
-#ifdef Py_USING_UNICODE
- /* Convert Unicode to a string using the default encoding */
- if (PyUnicode_Check(v)) {
- PyObject *temp = v;
- v = PyUnicode_AsEncodedString(v, NULL, NULL);
- Py_DECREF(temp);
- if (v == NULL)
- goto onError;
- }
-#endif
- if (!PyString_Check(v)) {
- PyErr_Format(PyExc_TypeError,
- "decoder did not return a string object (type=%.400s)",
- v->ob_type->tp_name);
- Py_DECREF(v);
- goto onError;
- }
-
- return v;
-
- onError:
- return NULL;
-}
-
-PyObject *PyString_Encode(const char *s,
- Py_ssize_t size,
- const char *encoding,
- const char *errors)
-{
- PyObject *v, *str;
-
- str = PyString_FromStringAndSize(s, size);
- if (str == NULL)
- return NULL;
- v = PyString_AsEncodedString(str, encoding, errors);
- Py_DECREF(str);
- return v;
-}
-
-PyObject *PyString_AsEncodedObject(PyObject *str,
- const char *encoding,
- const char *errors)
-{
- PyObject *v;
-
- if (!PyString_Check(str)) {
- PyErr_BadArgument();
- goto onError;
- }
-
- if (encoding == NULL) {
-#ifdef Py_USING_UNICODE
- encoding = PyUnicode_GetDefaultEncoding();
-#else
- PyErr_SetString(PyExc_ValueError, "no encoding specified");
- goto onError;
-#endif
- }
-
- /* Encode via the codec registry */
- v = PyCodec_Encode(str, encoding, errors);
- if (v == NULL)
- goto onError;
-
- return v;
-
- onError:
- return NULL;
-}
-
-PyObject *PyString_AsEncodedString(PyObject *str,
- const char *encoding,
- const char *errors)
-{
- PyObject *v;
-
- v = PyString_AsEncodedObject(str, encoding, errors);
- if (v == NULL)
- goto onError;
-
-#ifdef Py_USING_UNICODE
- /* Convert Unicode to a string using the default encoding */
- if (PyUnicode_Check(v)) {
- PyObject *temp = v;
- v = PyUnicode_AsEncodedString(v, NULL, NULL);
- Py_DECREF(temp);
- if (v == NULL)
- goto onError;
- }
-#endif
- if (!PyString_Check(v)) {
- PyErr_Format(PyExc_TypeError,
- "encoder did not return a string object (type=%.400s)",
- v->ob_type->tp_name);
- Py_DECREF(v);
- goto onError;
- }
-
- return v;
-
- onError:
- return NULL;
-}
-
-static void
-string_dealloc(PyObject *op)
-{
- switch (PyString_CHECK_INTERNED(op)) {
- case SSTATE_NOT_INTERNED:
- break;
-
- case SSTATE_INTERNED_MORTAL:
- /* revive dead object temporarily for DelItem */
- op->ob_refcnt = 3;
- if (PyDict_DelItem(interned, op) != 0)
- Py_FatalError(
- "deletion of interned string failed");
- break;
-
- case SSTATE_INTERNED_IMMORTAL:
- Py_FatalError("Immortal interned string died.");
-
- default:
- Py_FatalError("Inconsistent interned string state.");
- }
- op->ob_type->tp_free(op);
-}
-
-/* Unescape a backslash-escaped string. If unicode is non-zero,
- the string is a u-literal. If recode_encoding is non-zero,
- the string is UTF-8 encoded and should be re-encoded in the
- specified encoding. */
-
-PyObject *PyString_DecodeEscape(const char *s,
- Py_ssize_t len,
- const char *errors,
- Py_ssize_t unicode,
- const char *recode_encoding)
-{
- int c;
- char *p, *buf;
- const char *end;
- PyObject *v;
- Py_ssize_t newlen = recode_encoding ? 4*len:len;
- v = PyString_FromStringAndSize((char *)NULL, newlen);
- if (v == NULL)
- return NULL;
- p = buf = PyString_AsString(v);
- end = s + len;
- while (s < end) {
- if (*s != '\\') {
- non_esc:
-#ifdef Py_USING_UNICODE
- if (recode_encoding && (*s & 0x80)) {
- PyObject *u, *w;
- char *r;
- const char* t;
- Py_ssize_t rn;
- t = s;
- /* Decode non-ASCII bytes as UTF-8. */
- while (t < end && (*t & 0x80)) t++;
- u = PyUnicode_DecodeUTF8(s, t - s, errors);
- if(!u) goto failed;
-
- /* Recode them in target encoding. */
- w = PyUnicode_AsEncodedString(
- u, recode_encoding, errors);
- Py_DECREF(u);
- if (!w) goto failed;
-
- /* Append bytes to output buffer. */
- assert(PyString_Check(w));
- r = PyString_AS_STRING(w);
- rn = PyString_GET_SIZE(w);
- Py_MEMCPY(p, r, rn);
- p += rn;
- Py_DECREF(w);
- s = t;
- } else {
- *p++ = *s++;
- }
-#else
- *p++ = *s++;
-#endif
- continue;
- }
- s++;
- if (s==end) {
- PyErr_SetString(PyExc_ValueError,
- "Trailing \\ in string");
- goto failed;
- }
- switch (*s++) {
- /* XXX This assumes ASCII! */
- case '\n': break;
- case '\\': *p++ = '\\'; break;
- case '\'': *p++ = '\''; break;
- case '\"': *p++ = '\"'; break;
- case 'b': *p++ = '\b'; break;
- case 'f': *p++ = '\014'; break; /* FF */
- case 't': *p++ = '\t'; break;
- case 'n': *p++ = '\n'; break;
- case 'r': *p++ = '\r'; break;
- case 'v': *p++ = '\013'; break; /* VT */
- case 'a': *p++ = '\007'; break; /* BEL, not classic C */
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- c = s[-1] - '0';
- if ('0' <= *s && *s <= '7') {
- c = (c<<3) + *s++ - '0';
- if ('0' <= *s && *s <= '7')
- c = (c<<3) + *s++ - '0';
- }
- *p++ = c;
- break;
- case 'x':
- if (isxdigit(Py_CHARMASK(s[0]))
- && isxdigit(Py_CHARMASK(s[1]))) {
- unsigned int x = 0;
- c = Py_CHARMASK(*s);
- s++;
- if (isdigit(c))
- x = c - '0';
- else if (islower(c))
- x = 10 + c - 'a';
- else
- x = 10 + c - 'A';
- x = x << 4;
- c = Py_CHARMASK(*s);
- s++;
- if (isdigit(c))
- x += c - '0';
- else if (islower(c))
- x += 10 + c - 'a';
- else
- x += 10 + c - 'A';
- *p++ = x;
- break;
- }
- if (!errors || strcmp(errors, "strict") == 0) {
- PyErr_SetString(PyExc_ValueError,
- "invalid \\x escape");
- goto failed;
- }
- if (strcmp(errors, "replace") == 0) {
- *p++ = '?';
- } else if (strcmp(errors, "ignore") == 0)
- /* do nothing */;
- else {
- PyErr_Format(PyExc_ValueError,
- "decoding error; "
- "unknown error handling code: %.400s",
- errors);
- goto failed;
- }
-#ifndef Py_USING_UNICODE
- case 'u':
- case 'U':
- case 'N':
- if (unicode) {
- PyErr_SetString(PyExc_ValueError,
- "Unicode escapes not legal "
- "when Unicode disabled");
- goto failed;
- }
-#endif
- default:
- *p++ = '\\';
- s--;
- goto non_esc; /* an arbitry number of unescaped
- UTF-8 bytes may follow. */
- }
- }
- if (p-buf < newlen)
- _PyString_Resize(&v, p - buf);
- return v;
- failed:
- Py_DECREF(v);
- return NULL;
-}
-
-/* -------------------------------------------------------------------- */
-/* object api */
-
-static Py_ssize_t
-string_getsize(register PyObject *op)
-{
- char *s;
- Py_ssize_t len;
- if (PyString_AsStringAndSize(op, &s, &len))
- return -1;
- return len;
-}
-
-static /*const*/ char *
-string_getbuffer(register PyObject *op)
-{
- char *s;
- Py_ssize_t len;
- if (PyString_AsStringAndSize(op, &s, &len))
- return NULL;
- return s;
-}
-
-Py_ssize_t
-PyString_Size(register PyObject *op)
-{
- if (!PyString_Check(op))
- return string_getsize(op);
- return ((PyStringObject *)op) -> ob_size;
-}
-
-/*const*/ char *
-PyString_AsString(register PyObject *op)
-{
- if (!PyString_Check(op))
- return string_getbuffer(op);
- return ((PyStringObject *)op) -> ob_sval;
-}
-
-int
-PyString_AsStringAndSize(register PyObject *obj,
- register char **s,
- register Py_ssize_t *len)
-{
- if (s == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
-
- if (!PyString_Check(obj)) {
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(obj)) {
- obj = _PyUnicode_AsDefaultEncodedString(obj, NULL);
- if (obj == NULL)
- return -1;
- }
- else
-#endif
- {
- PyErr_Format(PyExc_TypeError,
- "expected string or Unicode object, "
- "%.200s found", obj->ob_type->tp_name);
- return -1;
- }
- }
-
- *s = PyString_AS_STRING(obj);
- if (len != NULL)
- *len = PyString_GET_SIZE(obj);
- else if (strlen(*s) != (size_t)PyString_GET_SIZE(obj)) {
- PyErr_SetString(PyExc_TypeError,
- "expected string without null bytes");
- return -1;
- }
- return 0;
-}
-
-/* -------------------------------------------------------------------- */
-/* Methods */
-
-#define STRINGLIB_CHAR char
-
-#define STRINGLIB_CMP memcmp
-#define STRINGLIB_LEN PyString_GET_SIZE
-#define STRINGLIB_NEW PyString_FromStringAndSize
-#define STRINGLIB_STR PyString_AS_STRING
-
-#define STRINGLIB_EMPTY nullstring
-
-#include "stringlib/fastsearch.h"
-
-#include "stringlib/count.h"
-#include "stringlib/find.h"
-#include "stringlib/partition.h"
-
-
-static int
-string_print(PyStringObject *op, FILE *fp, int flags)
-{
- Py_ssize_t i;
- char c;
- int quote;
-
- /* XXX Ought to check for interrupts when writing long strings */
- if (! PyString_CheckExact(op)) {
- int ret;
- /* A str subclass may have its own __str__ method. */
- op = (PyStringObject *) PyObject_Str((PyObject *)op);
- if (op == NULL)
- return -1;
- ret = string_print(op, fp, flags);
- Py_DECREF(op);
- return ret;
- }
- if (flags & Py_PRINT_RAW) {
- char *data = op->ob_sval;
- Py_ssize_t size = op->ob_size;
- while (size > INT_MAX) {
- /* Very long strings cannot be written atomically.
- * But don't write exactly INT_MAX bytes at a time
- * to avoid memory aligment issues.
- */
- const int chunk_size = INT_MAX & ~0x3FFF;
- fwrite(data, 1, chunk_size, fp);
- data += chunk_size;
- size -= chunk_size;
- }
-#ifdef __VMS
- if (size) fwrite(data, (int)size, 1, fp);
-#else
- fwrite(data, 1, (int)size, fp);
-#endif
- return 0;
- }
-
- /* figure out which quote to use; single is preferred */
- quote = '\'';
- if (memchr(op->ob_sval, '\'', op->ob_size) &&
- !memchr(op->ob_sval, '"', op->ob_size))
- quote = '"';
-
- fputc(quote, fp);
- for (i = 0; i < op->ob_size; i++) {
- c = op->ob_sval[i];
- if (c == quote || c == '\\')
- fprintf(fp, "\\%c", c);
- else if (c == '\t')
- fprintf(fp, "\\t");
- else if (c == '\n')
- fprintf(fp, "\\n");
- else if (c == '\r')
- fprintf(fp, "\\r");
- else if (c < ' ' || c >= 0x7f)
- fprintf(fp, "\\x%02x", c & 0xff);
- else
- fputc(c, fp);
- }
- fputc(quote, fp);
- return 0;
-}
-
-PyObject *
-PyString_Repr(PyObject *obj, int smartquotes)
-{
- register PyStringObject* op = (PyStringObject*) obj;
- size_t newsize = 2 + 4 * op->ob_size;
- PyObject *v;
- if (newsize > PY_SSIZE_T_MAX || newsize / 4 != op->ob_size) {
- PyErr_SetString(PyExc_OverflowError,
- "string is too large to make repr");
- }
- v = PyString_FromStringAndSize((char *)NULL, newsize);
- if (v == NULL) {
- return NULL;
- }
- else {
- register Py_ssize_t i;
- register char c;
- register char *p;
- int quote;
-
- /* figure out which quote to use; single is preferred */
- quote = '\'';
- if (smartquotes &&
- memchr(op->ob_sval, '\'', op->ob_size) &&
- !memchr(op->ob_sval, '"', op->ob_size))
- quote = '"';
-
- p = PyString_AS_STRING(v);
- *p++ = quote;
- for (i = 0; i < op->ob_size; i++) {
- /* There's at least enough room for a hex escape
- and a closing quote. */
- assert(newsize - (p - PyString_AS_STRING(v)) >= 5);
- c = op->ob_sval[i];
- if (c == quote || c == '\\')
- *p++ = '\\', *p++ = c;
- else if (c == '\t')
- *p++ = '\\', *p++ = 't';
- else if (c == '\n')
- *p++ = '\\', *p++ = 'n';
- else if (c == '\r')
- *p++ = '\\', *p++ = 'r';
- else if (c < ' ' || c >= 0x7f) {
- /* For performance, we don't want to call
- PyOS_snprintf here (extra layers of
- function call). */
- sprintf(p, "\\x%02x", c & 0xff);
- p += 4;
- }
- else
- *p++ = c;
- }
- assert(newsize - (p - PyString_AS_STRING(v)) >= 1);
- *p++ = quote;
- *p = '\0';
- _PyString_Resize(
- &v, (p - PyString_AS_STRING(v)));
- return v;
- }
-}
-
-static PyObject *
-string_repr(PyObject *op)
-{
- return PyString_Repr(op, 1);
-}
-
-static PyObject *
-string_str(PyObject *s)
-{
- assert(PyString_Check(s));
- if (PyString_CheckExact(s)) {
- Py_INCREF(s);
- return s;
- }
- else {
- /* Subtype -- return genuine string with the same value. */
- PyStringObject *t = (PyStringObject *) s;
- return PyString_FromStringAndSize(t->ob_sval, t->ob_size);
- }
-}
-
-static Py_ssize_t
-string_length(PyStringObject *a)
-{
- return a->ob_size;
-}
-
-static PyObject *
-string_concat(register PyStringObject *a, register PyObject *bb)
-{
- register Py_ssize_t size;
- register PyStringObject *op;
- if (!PyString_Check(bb)) {
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(bb))
- return PyUnicode_Concat((PyObject *)a, bb);
-#endif
- PyErr_Format(PyExc_TypeError,
- "cannot concatenate 'str' and '%.200s' objects",
- bb->ob_type->tp_name);
- return NULL;
- }
-#define b ((PyStringObject *)bb)
- /* Optimize cases with empty left or right operand */
- if ((a->ob_size == 0 || b->ob_size == 0) &&
- PyString_CheckExact(a) && PyString_CheckExact(b)) {
- if (a->ob_size == 0) {
- Py_INCREF(bb);
- return bb;
- }
- Py_INCREF(a);
- return (PyObject *)a;
- }
- size = a->ob_size + b->ob_size;
- if (size < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "strings are too large to concat");
- return NULL;
- }
-
- /* Inline PyObject_NewVar */
- op = (PyStringObject *)PyObject_MALLOC(sizeof(PyStringObject) + size);
- if (op == NULL)
- return PyErr_NoMemory();
- PyObject_INIT_VAR(op, &PyString_Type, size);
- op->ob_shash = -1;
- op->ob_sstate = SSTATE_NOT_INTERNED;
- Py_MEMCPY(op->ob_sval, a->ob_sval, a->ob_size);
- Py_MEMCPY(op->ob_sval + a->ob_size, b->ob_sval, b->ob_size);
- op->ob_sval[size] = '\0';
- return (PyObject *) op;
-#undef b
-}
-
-static PyObject *
-string_repeat(register PyStringObject *a, register Py_ssize_t n)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- register Py_ssize_t size;
- register PyStringObject *op;
- size_t nbytes;
- if (n < 0)
- n = 0;
- /* watch out for overflows: the size can overflow int,
- * and the # of bytes needed can overflow size_t
- */
- size = a->ob_size * n;
- if (n && size / n != a->ob_size) {
- PyErr_SetString(PyExc_OverflowError,
- "repeated string is too long");
- return NULL;
- }
- if (size == a->ob_size && PyString_CheckExact(a)) {
- Py_INCREF(a);
- return (PyObject *)a;
- }
- nbytes = (size_t)size;
- if (nbytes + sizeof(PyStringObject) <= nbytes) {
- PyErr_SetString(PyExc_OverflowError,
- "repeated string is too long");
- return NULL;
- }
- op = (PyStringObject *)
- PyObject_MALLOC(sizeof(PyStringObject) + nbytes);
- if (op == NULL)
- return PyErr_NoMemory();
- PyObject_INIT_VAR(op, &PyString_Type, size);
- op->ob_shash = -1;
- op->ob_sstate = SSTATE_NOT_INTERNED;
- op->ob_sval[size] = '\0';
- if (a->ob_size == 1 && n > 0) {
- memset(op->ob_sval, a->ob_sval[0] , n);
- return (PyObject *) op;
- }
- i = 0;
- if (i < size) {
- Py_MEMCPY(op->ob_sval, a->ob_sval, a->ob_size);
- i = a->ob_size;
- }
- while (i < size) {
- j = (i <= size-i) ? i : size-i;
- Py_MEMCPY(op->ob_sval+i, op->ob_sval, j);
- i += j;
- }
- return (PyObject *) op;
-}
-
-/* String slice a[i:j] consists of characters a[i] ... a[j-1] */
-
-static PyObject *
-string_slice(register PyStringObject *a, register Py_ssize_t i,
- register Py_ssize_t j)
- /* j -- may be negative! */
-{
- if (i < 0)
- i = 0;
- if (j < 0)
- j = 0; /* Avoid signed/unsigned bug in next line */
- if (j > a->ob_size)
- j = a->ob_size;
- if (i == 0 && j == a->ob_size && PyString_CheckExact(a)) {
- /* It's the same as a */
- Py_INCREF(a);
- return (PyObject *)a;
- }
- if (j < i)
- j = i;
- return PyString_FromStringAndSize(a->ob_sval + i, j-i);
-}
-
-static int
-string_contains(PyObject *str_obj, PyObject *sub_obj)
-{
- if (!PyString_CheckExact(sub_obj)) {
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(sub_obj))
- return PyUnicode_Contains(str_obj, sub_obj);
-#endif
- if (!PyString_Check(sub_obj)) {
- PyErr_SetString(PyExc_TypeError,
- "'in <string>' requires string as left operand");
- return -1;
- }
- }
-
- return stringlib_contains_obj(str_obj, sub_obj);
-}
-
-static PyObject *
-string_item(PyStringObject *a, register Py_ssize_t i)
-{
- char pchar;
- PyObject *v;
- if (i < 0 || i >= a->ob_size) {
- PyErr_SetString(PyExc_IndexError, "string index out of range");
- return NULL;
- }
- pchar = a->ob_sval[i];
- v = (PyObject *)characters[pchar & UCHAR_MAX];
- if (v == NULL)
- v = PyString_FromStringAndSize(&pchar, 1);
- else {
-#ifdef COUNT_ALLOCS
- one_strings++;
-#endif
- Py_INCREF(v);
- }
- return v;
-}
-
-static PyObject*
-string_richcompare(PyStringObject *a, PyStringObject *b, int op)
-{
- int c;
- Py_ssize_t len_a, len_b;
- Py_ssize_t min_len;
- PyObject *result;
-
- /* Make sure both arguments are strings. */
- if (!(PyString_Check(a) && PyString_Check(b))) {
- result = Py_NotImplemented;
- goto out;
- }
- if (a == b) {
- switch (op) {
- case Py_EQ:case Py_LE:case Py_GE:
- result = Py_True;
- goto out;
- case Py_NE:case Py_LT:case Py_GT:
- result = Py_False;
- goto out;
- }
- }
- if (op == Py_EQ) {
- /* Supporting Py_NE here as well does not save
- much time, since Py_NE is rarely used. */
- if (a->ob_size == b->ob_size
- && (a->ob_sval[0] == b->ob_sval[0]
- && memcmp(a->ob_sval, b->ob_sval,
- a->ob_size) == 0)) {
- result = Py_True;
- } else {
- result = Py_False;
- }
- goto out;
- }
- len_a = a->ob_size; len_b = b->ob_size;
- min_len = (len_a < len_b) ? len_a : len_b;
- if (min_len > 0) {
- c = Py_CHARMASK(*a->ob_sval) - Py_CHARMASK(*b->ob_sval);
- if (c==0)
- c = memcmp(a->ob_sval, b->ob_sval, min_len);
- }else
- c = 0;
- if (c == 0)
- c = (len_a < len_b) ? -1 : (len_a > len_b) ? 1 : 0;
- switch (op) {
- case Py_LT: c = c < 0; break;
- case Py_LE: c = c <= 0; break;
- case Py_EQ: assert(0); break; /* unreachable */
- case Py_NE: c = c != 0; break;
- case Py_GT: c = c > 0; break;
- case Py_GE: c = c >= 0; break;
- default:
- result = Py_NotImplemented;
- goto out;
- }
- result = c ? Py_True : Py_False;
- out:
- Py_INCREF(result);
- return result;
-}
-
-int
-_PyString_Eq(PyObject *o1, PyObject *o2)
-{
- PyStringObject *a = (PyStringObject*) o1;
- PyStringObject *b = (PyStringObject*) o2;
- return a->ob_size == b->ob_size
- && *a->ob_sval == *b->ob_sval
- && memcmp(a->ob_sval, b->ob_sval, a->ob_size) == 0;
-}
-
-static long
-string_hash(PyStringObject *a)
-{
- register Py_ssize_t len;
- register unsigned char *p;
- register long x;
-
- if (a->ob_shash != -1)
- return a->ob_shash;
- len = a->ob_size;
- p = (unsigned char *) a->ob_sval;
- x = *p << 7;
- while (--len >= 0)
- x = (1000003*x) ^ *p++;
- x ^= a->ob_size;
- if (x == -1)
- x = -2;
- a->ob_shash = x;
- return x;
-}
-
-static PyObject*
-string_subscript(PyStringObject* self, PyObject* item)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += PyString_GET_SIZE(self);
- return string_item(self, i);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength, cur, i;
- char* source_buf;
- char* result_buf;
- PyObject* result;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item,
- PyString_GET_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
- return NULL;
- }
-
- if (slicelength <= 0) {
- return PyString_FromStringAndSize("", 0);
- }
- else {
- source_buf = PyString_AsString((PyObject*)self);
- result_buf = (char *)PyMem_Malloc(slicelength);
- if (result_buf == NULL)
- return PyErr_NoMemory();
-
- for (cur = start, i = 0; i < slicelength;
- cur += step, i++) {
- result_buf[i] = source_buf[cur];
- }
-
- result = PyString_FromStringAndSize(result_buf,
- slicelength);
- PyMem_Free(result_buf);
- return result;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "string indices must be integers");
- return NULL;
- }
-}
-
-static Py_ssize_t
-string_buffer_getreadbuf(PyStringObject *self, Py_ssize_t index, const void **ptr)
-{
- if ( index != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent string segment");
- return -1;
- }
- *ptr = (void *)self->ob_sval;
- return self->ob_size;
-}
-
-static Py_ssize_t
-string_buffer_getwritebuf(PyStringObject *self, Py_ssize_t index, const void **ptr)
-{
- PyErr_SetString(PyExc_TypeError,
- "Cannot use string as modifiable buffer");
- return -1;
-}
-
-static Py_ssize_t
-string_buffer_getsegcount(PyStringObject *self, Py_ssize_t *lenp)
-{
- if ( lenp )
- *lenp = self->ob_size;
- return 1;
-}
-
-static Py_ssize_t
-string_buffer_getcharbuf(PyStringObject *self, Py_ssize_t index, const char **ptr)
-{
- if ( index != 0 ) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent string segment");
- return -1;
- }
- *ptr = self->ob_sval;
- return self->ob_size;
-}
-
-static PySequenceMethods string_as_sequence = {
- (lenfunc)string_length, /*sq_length*/
- (binaryfunc)string_concat, /*sq_concat*/
- (ssizeargfunc)string_repeat, /*sq_repeat*/
- (ssizeargfunc)string_item, /*sq_item*/
- (ssizessizeargfunc)string_slice, /*sq_slice*/
- 0, /*sq_ass_item*/
- 0, /*sq_ass_slice*/
- (objobjproc)string_contains /*sq_contains*/
-};
-
-static PyMappingMethods string_as_mapping = {
- (lenfunc)string_length,
- (binaryfunc)string_subscript,
- 0,
-};
-
-static PyBufferProcs string_as_buffer = {
- (readbufferproc)string_buffer_getreadbuf,
- (writebufferproc)string_buffer_getwritebuf,
- (segcountproc)string_buffer_getsegcount,
- (charbufferproc)string_buffer_getcharbuf,
-};
-
-
-
-#define LEFTSTRIP 0
-#define RIGHTSTRIP 1
-#define BOTHSTRIP 2
-
-/* Arrays indexed by above */
-static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"};
-
-#define STRIPNAME(i) (stripformat[i]+3)
-
-
-/* Don't call if length < 2 */
-#define Py_STRING_MATCH(target, offset, pattern, length) \
- (target[offset] == pattern[0] && \
- target[offset+length-1] == pattern[length-1] && \
- !memcmp(target+offset+1, pattern+1, length-2) )
-
-
-/* Overallocate the initial list to reduce the number of reallocs for small
- split sizes. Eg, "A A A A A A A A A A".split() (10 elements) has three
- resizes, to sizes 4, 8, then 16. Most observed string splits are for human
- text (roughly 11 words per line) and field delimited data (usually 1-10
- fields). For large strings the split algorithms are bandwidth limited
- so increasing the preallocation likely will not improve things.*/
-
-#define MAX_PREALLOC 12
-
-/* 5 splits gives 6 elements */
-#define PREALLOC_SIZE(maxsplit) \
- (maxsplit >= MAX_PREALLOC ? MAX_PREALLOC : maxsplit+1)
-
-#define SPLIT_APPEND(data, left, right) \
- str = PyString_FromStringAndSize((data) + (left), \
- (right) - (left)); \
- if (str == NULL) \
- goto onError; \
- if (PyList_Append(list, str)) { \
- Py_DECREF(str); \
- goto onError; \
- } \
- else \
- Py_DECREF(str);
-
-#define SPLIT_ADD(data, left, right) { \
- str = PyString_FromStringAndSize((data) + (left), \
- (right) - (left)); \
- if (str == NULL) \
- goto onError; \
- if (count < MAX_PREALLOC) { \
- PyList_SET_ITEM(list, count, str); \
- } else { \
- if (PyList_Append(list, str)) { \
- Py_DECREF(str); \
- goto onError; \
- } \
- else \
- Py_DECREF(str); \
- } \
- count++; }
-
-/* Always force the list to the expected size. */
-#define FIX_PREALLOC_SIZE(list) ((PyListObject *)list)->ob_size = count
-
-#define SKIP_SPACE(s, i, len) { while (i<len && isspace(Py_CHARMASK(s[i]))) i++; }
-#define SKIP_NONSPACE(s, i, len) { while (i<len && !isspace(Py_CHARMASK(s[i]))) i++; }
-#define RSKIP_SPACE(s, i) { while (i>=0 && isspace(Py_CHARMASK(s[i]))) i--; }
-#define RSKIP_NONSPACE(s, i) { while (i>=0 && !isspace(Py_CHARMASK(s[i]))) i--; }
-
-Py_LOCAL_INLINE(PyObject *)
-split_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit)
-{
- Py_ssize_t i, j, count=0;
- PyObject *str;
- PyObject *list = PyList_New(PREALLOC_SIZE(maxsplit));
-
- if (list == NULL)
- return NULL;
-
- i = j = 0;
-
- while (maxsplit-- > 0) {
- SKIP_SPACE(s, i, len);
- if (i==len) break;
- j = i; i++;
- SKIP_NONSPACE(s, i, len);
- SPLIT_ADD(s, j, i);
- }
-
- if (i < len) {
- /* Only occurs when maxsplit was reached */
- /* Skip any remaining whitespace and copy to end of string */
- SKIP_SPACE(s, i, len);
- if (i != len)
- SPLIT_ADD(s, i, len);
- }
- FIX_PREALLOC_SIZE(list);
- return list;
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-Py_LOCAL_INLINE(PyObject *)
-split_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount)
-{
- register Py_ssize_t i, j, count=0;
- PyObject *str;
- PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
-
- if (list == NULL)
- return NULL;
-
- i = j = 0;
- while ((j < len) && (maxcount-- > 0)) {
- for(; j<len; j++) {
- /* I found that using memchr makes no difference */
- if (s[j] == ch) {
- SPLIT_ADD(s, i, j);
- i = j = j + 1;
- break;
- }
- }
- }
- if (i <= len) {
- SPLIT_ADD(s, i, len);
- }
- FIX_PREALLOC_SIZE(list);
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-PyDoc_STRVAR(split__doc__,
-"S.split([sep [,maxsplit]]) -> list of strings\n\
-\n\
-Return a list of the words in the string S, using sep as the\n\
-delimiter string. If maxsplit is given, at most maxsplit\n\
-splits are done. If sep is not specified or is None, any\n\
-whitespace string is a separator.");
-
-static PyObject *
-string_split(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t len = PyString_GET_SIZE(self), n, i, j;
- Py_ssize_t maxsplit = -1, count=0;
- const char *s = PyString_AS_STRING(self), *sub;
- PyObject *list, *str, *subobj = Py_None;
-#ifdef USE_FAST
- Py_ssize_t pos;
-#endif
-
- if (!PyArg_ParseTuple(args, "|On:split", &subobj, &maxsplit))
- return NULL;
- if (maxsplit < 0)
- maxsplit = PY_SSIZE_T_MAX;
- if (subobj == Py_None)
- return split_whitespace(s, len, maxsplit);
- if (PyString_Check(subobj)) {
- sub = PyString_AS_STRING(subobj);
- n = PyString_GET_SIZE(subobj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(subobj))
- return PyUnicode_Split((PyObject *)self, subobj, maxsplit);
-#endif
- else if (PyObject_AsCharBuffer(subobj, &sub, &n))
- return NULL;
-
- if (n == 0) {
- PyErr_SetString(PyExc_ValueError, "empty separator");
- return NULL;
- }
- else if (n == 1)
- return split_char(s, len, sub[0], maxsplit);
-
- list = PyList_New(PREALLOC_SIZE(maxsplit));
- if (list == NULL)
- return NULL;
-
-#ifdef USE_FAST
- i = j = 0;
- while (maxsplit-- > 0) {
- pos = fastsearch(s+i, len-i, sub, n, FAST_SEARCH);
- if (pos < 0)
- break;
- j = i+pos;
- SPLIT_ADD(s, i, j);
- i = j + n;
- }
-#else
- i = j = 0;
- while ((j+n <= len) && (maxsplit-- > 0)) {
- for (; j+n <= len; j++) {
- if (Py_STRING_MATCH(s, j, sub, n)) {
- SPLIT_ADD(s, i, j);
- i = j = j + n;
- break;
- }
- }
- }
-#endif
- SPLIT_ADD(s, i, len);
- FIX_PREALLOC_SIZE(list);
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-PyDoc_STRVAR(partition__doc__,
-"S.partition(sep) -> (head, sep, tail)\n\
-\n\
-Searches for the separator sep in S, and returns the part before it,\n\
-the separator itself, and the part after it. If the separator is not\n\
-found, returns S and two empty strings.");
-
-static PyObject *
-string_partition(PyStringObject *self, PyObject *sep_obj)
-{
- const char *sep;
- Py_ssize_t sep_len;
-
- if (PyString_Check(sep_obj)) {
- sep = PyString_AS_STRING(sep_obj);
- sep_len = PyString_GET_SIZE(sep_obj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(sep_obj))
- return PyUnicode_Partition((PyObject *) self, sep_obj);
-#endif
- else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
- return NULL;
-
- return stringlib_partition(
- (PyObject*) self,
- PyString_AS_STRING(self), PyString_GET_SIZE(self),
- sep_obj, sep, sep_len
- );
-}
-
-PyDoc_STRVAR(rpartition__doc__,
-"S.rpartition(sep) -> (tail, sep, head)\n\
-\n\
-Searches for the separator sep in S, starting at the end of S, and returns\n\
-the part before it, the separator itself, and the part after it. If the\n\
-separator is not found, returns two empty strings and S.");
-
-static PyObject *
-string_rpartition(PyStringObject *self, PyObject *sep_obj)
-{
- const char *sep;
- Py_ssize_t sep_len;
-
- if (PyString_Check(sep_obj)) {
- sep = PyString_AS_STRING(sep_obj);
- sep_len = PyString_GET_SIZE(sep_obj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(sep_obj))
- return PyUnicode_Partition((PyObject *) self, sep_obj);
-#endif
- else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len))
- return NULL;
-
- return stringlib_rpartition(
- (PyObject*) self,
- PyString_AS_STRING(self), PyString_GET_SIZE(self),
- sep_obj, sep, sep_len
- );
-}
-
-Py_LOCAL_INLINE(PyObject *)
-rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit)
-{
- Py_ssize_t i, j, count=0;
- PyObject *str;
- PyObject *list = PyList_New(PREALLOC_SIZE(maxsplit));
-
- if (list == NULL)
- return NULL;
-
- i = j = len-1;
-
- while (maxsplit-- > 0) {
- RSKIP_SPACE(s, i);
- if (i<0) break;
- j = i; i--;
- RSKIP_NONSPACE(s, i);
- SPLIT_ADD(s, i + 1, j + 1);
- }
- if (i >= 0) {
- /* Only occurs when maxsplit was reached */
- /* Skip any remaining whitespace and copy to beginning of string */
- RSKIP_SPACE(s, i);
- if (i >= 0)
- SPLIT_ADD(s, 0, i + 1);
-
- }
- FIX_PREALLOC_SIZE(list);
- if (PyList_Reverse(list) < 0)
- goto onError;
- return list;
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-Py_LOCAL_INLINE(PyObject *)
-rsplit_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount)
-{
- register Py_ssize_t i, j, count=0;
- PyObject *str;
- PyObject *list = PyList_New(PREALLOC_SIZE(maxcount));
-
- if (list == NULL)
- return NULL;
-
- i = j = len - 1;
- while ((i >= 0) && (maxcount-- > 0)) {
- for (; i >= 0; i--) {
- if (s[i] == ch) {
- SPLIT_ADD(s, i + 1, j + 1);
- j = i = i - 1;
- break;
- }
- }
- }
- if (j >= -1) {
- SPLIT_ADD(s, 0, j + 1);
- }
- FIX_PREALLOC_SIZE(list);
- if (PyList_Reverse(list) < 0)
- goto onError;
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-PyDoc_STRVAR(rsplit__doc__,
-"S.rsplit([sep [,maxsplit]]) -> list of strings\n\
-\n\
-Return a list of the words in the string S, using sep as the\n\
-delimiter string, starting at the end of the string and working\n\
-to the front. If maxsplit is given, at most maxsplit splits are\n\
-done. If sep is not specified or is None, any whitespace string\n\
-is a separator.");
-
-static PyObject *
-string_rsplit(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t len = PyString_GET_SIZE(self), n, i, j;
- Py_ssize_t maxsplit = -1, count=0;
- const char *s = PyString_AS_STRING(self), *sub;
- PyObject *list, *str, *subobj = Py_None;
-
- if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit))
- return NULL;
- if (maxsplit < 0)
- maxsplit = PY_SSIZE_T_MAX;
- if (subobj == Py_None)
- return rsplit_whitespace(s, len, maxsplit);
- if (PyString_Check(subobj)) {
- sub = PyString_AS_STRING(subobj);
- n = PyString_GET_SIZE(subobj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(subobj))
- return PyUnicode_RSplit((PyObject *)self, subobj, maxsplit);
-#endif
- else if (PyObject_AsCharBuffer(subobj, &sub, &n))
- return NULL;
-
- if (n == 0) {
- PyErr_SetString(PyExc_ValueError, "empty separator");
- return NULL;
- }
- else if (n == 1)
- return rsplit_char(s, len, sub[0], maxsplit);
-
- list = PyList_New(PREALLOC_SIZE(maxsplit));
- if (list == NULL)
- return NULL;
-
- j = len;
- i = j - n;
-
- while ( (i >= 0) && (maxsplit-- > 0) ) {
- for (; i>=0; i--) {
- if (Py_STRING_MATCH(s, i, sub, n)) {
- SPLIT_ADD(s, i + n, j);
- j = i;
- i -= n;
- break;
- }
- }
- }
- SPLIT_ADD(s, 0, j);
- FIX_PREALLOC_SIZE(list);
- if (PyList_Reverse(list) < 0)
- goto onError;
- return list;
-
-onError:
- Py_DECREF(list);
- return NULL;
-}
-
-
-PyDoc_STRVAR(join__doc__,
-"S.join(sequence) -> string\n\
-\n\
-Return a string which is the concatenation of the strings in the\n\
-sequence. The separator between elements is S.");
-
-static PyObject *
-string_join(PyStringObject *self, PyObject *orig)
-{
- char *sep = PyString_AS_STRING(self);
- const Py_ssize_t seplen = PyString_GET_SIZE(self);
- PyObject *res = NULL;
- char *p;
- Py_ssize_t seqlen = 0;
- size_t sz = 0;
- Py_ssize_t i;
- PyObject *seq, *item;
-
- seq = PySequence_Fast(orig, "");
- if (seq == NULL) {
- return NULL;
- }
-
- seqlen = PySequence_Size(seq);
- if (seqlen == 0) {
- Py_DECREF(seq);
- return PyString_FromString("");
- }
- if (seqlen == 1) {
- item = PySequence_Fast_GET_ITEM(seq, 0);
- if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) {
- Py_INCREF(item);
- Py_DECREF(seq);
- return item;
- }
- }
-
- /* There are at least two things to join, or else we have a subclass
- * of the builtin types in the sequence.
- * Do a pre-pass to figure out the total amount of space we'll
- * need (sz), see whether any argument is absurd, and defer to
- * the Unicode join if appropriate.
- */
- for (i = 0; i < seqlen; i++) {
- const size_t old_sz = sz;
- item = PySequence_Fast_GET_ITEM(seq, i);
- if (!PyString_Check(item)){
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(item)) {
- /* Defer to Unicode join.
- * CAUTION: There's no gurantee that the
- * original sequence can be iterated over
- * again, so we must pass seq here.
- */
- PyObject *result;
- result = PyUnicode_Join((PyObject *)self, seq);
- Py_DECREF(seq);
- return result;
- }
-#endif
- PyErr_Format(PyExc_TypeError,
- "sequence item %zd: expected string,"
- " %.80s found",
- i, item->ob_type->tp_name);
- Py_DECREF(seq);
- return NULL;
- }
- sz += PyString_GET_SIZE(item);
- if (i != 0)
- sz += seplen;
- if (sz < old_sz || sz > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "join() result is too long for a Python string");
- Py_DECREF(seq);
- return NULL;
- }
- }
-
- /* Allocate result space. */
- res = PyString_FromStringAndSize((char*)NULL, sz);
- if (res == NULL) {
- Py_DECREF(seq);
- return NULL;
- }
-
- /* Catenate everything. */
- p = PyString_AS_STRING(res);
- for (i = 0; i < seqlen; ++i) {
- size_t n;
- item = PySequence_Fast_GET_ITEM(seq, i);
- n = PyString_GET_SIZE(item);
- Py_MEMCPY(p, PyString_AS_STRING(item), n);
- p += n;
- if (i < seqlen - 1) {
- Py_MEMCPY(p, sep, seplen);
- p += seplen;
- }
- }
-
- Py_DECREF(seq);
- return res;
-}
-
-PyObject *
-_PyString_Join(PyObject *sep, PyObject *x)
-{
- assert(sep != NULL && PyString_Check(sep));
- assert(x != NULL);
- return string_join((PyStringObject *)sep, x);
-}
-
-Py_LOCAL_INLINE(void)
-string_adjust_indices(Py_ssize_t *start, Py_ssize_t *end, Py_ssize_t len)
-{
- if (*end > len)
- *end = len;
- else if (*end < 0)
- *end += len;
- if (*end < 0)
- *end = 0;
- if (*start < 0)
- *start += len;
- if (*start < 0)
- *start = 0;
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-string_find_internal(PyStringObject *self, PyObject *args, int dir)
-{
- PyObject *subobj;
- const char *sub;
- Py_ssize_t sub_len;
- Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", &subobj,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return -2;
- if (PyString_Check(subobj)) {
- sub = PyString_AS_STRING(subobj);
- sub_len = PyString_GET_SIZE(subobj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(subobj))
- return PyUnicode_Find(
- (PyObject *)self, subobj, start, end, dir);
-#endif
- else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len))
- /* XXX - the "expected a character buffer object" is pretty
- confusing for a non-expert. remap to something else ? */
- return -2;
-
- if (dir > 0)
- return stringlib_find_slice(
- PyString_AS_STRING(self), PyString_GET_SIZE(self),
- sub, sub_len, start, end);
- else
- return stringlib_rfind_slice(
- PyString_AS_STRING(self), PyString_GET_SIZE(self),
- sub, sub_len, start, end);
-}
-
-
-PyDoc_STRVAR(find__doc__,
-"S.find(sub [,start [,end]]) -> int\n\
-\n\
-Return the lowest index in S where substring sub is found,\n\
-such that sub is contained within s[start,end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
-static PyObject *
-string_find(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t result = string_find_internal(self, args, +1);
- if (result == -2)
- return NULL;
- return PyInt_FromSsize_t(result);
-}
-
-
-PyDoc_STRVAR(index__doc__,
-"S.index(sub [,start [,end]]) -> int\n\
-\n\
-Like S.find() but raise ValueError when the substring is not found.");
-
-static PyObject *
-string_index(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t result = string_find_internal(self, args, +1);
- if (result == -2)
- return NULL;
- if (result == -1) {
- PyErr_SetString(PyExc_ValueError,
- "substring not found");
- return NULL;
- }
- return PyInt_FromSsize_t(result);
-}
-
-
-PyDoc_STRVAR(rfind__doc__,
-"S.rfind(sub [,start [,end]]) -> int\n\
-\n\
-Return the highest index in S where substring sub is found,\n\
-such that sub is contained within s[start,end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
-static PyObject *
-string_rfind(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t result = string_find_internal(self, args, -1);
- if (result == -2)
- return NULL;
- return PyInt_FromSsize_t(result);
-}
-
-
-PyDoc_STRVAR(rindex__doc__,
-"S.rindex(sub [,start [,end]]) -> int\n\
-\n\
-Like S.rfind() but raise ValueError when the substring is not found.");
-
-static PyObject *
-string_rindex(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t result = string_find_internal(self, args, -1);
- if (result == -2)
- return NULL;
- if (result == -1) {
- PyErr_SetString(PyExc_ValueError,
- "substring not found");
- return NULL;
- }
- return PyInt_FromSsize_t(result);
-}
-
-
-Py_LOCAL_INLINE(PyObject *)
-do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj)
-{
- char *s = PyString_AS_STRING(self);
- Py_ssize_t len = PyString_GET_SIZE(self);
- char *sep = PyString_AS_STRING(sepobj);
- Py_ssize_t seplen = PyString_GET_SIZE(sepobj);
- Py_ssize_t i, j;
-
- i = 0;
- if (striptype != RIGHTSTRIP) {
- while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) {
- i++;
- }
- }
-
- j = len;
- if (striptype != LEFTSTRIP) {
- do {
- j--;
- } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen));
- j++;
- }
-
- if (i == 0 && j == len && PyString_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*)self;
- }
- else
- return PyString_FromStringAndSize(s+i, j-i);
-}
-
-
-Py_LOCAL_INLINE(PyObject *)
-do_strip(PyStringObject *self, int striptype)
-{
- char *s = PyString_AS_STRING(self);
- Py_ssize_t len = PyString_GET_SIZE(self), i, j;
-
- i = 0;
- if (striptype != RIGHTSTRIP) {
- while (i < len && isspace(Py_CHARMASK(s[i]))) {
- i++;
- }
- }
-
- j = len;
- if (striptype != LEFTSTRIP) {
- do {
- j--;
- } while (j >= i && isspace(Py_CHARMASK(s[j])));
- j++;
- }
-
- if (i == 0 && j == len && PyString_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*)self;
- }
- else
- return PyString_FromStringAndSize(s+i, j-i);
-}
-
-
-Py_LOCAL_INLINE(PyObject *)
-do_argstrip(PyStringObject *self, int striptype, PyObject *args)
-{
- PyObject *sep = NULL;
-
- if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep))
- return NULL;
-
- if (sep != NULL && sep != Py_None) {
- if (PyString_Check(sep))
- return do_xstrip(self, striptype, sep);
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(sep)) {
- PyObject *uniself = PyUnicode_FromObject((PyObject *)self);
- PyObject *res;
- if (uniself==NULL)
- return NULL;
- res = _PyUnicode_XStrip((PyUnicodeObject *)uniself,
- striptype, sep);
- Py_DECREF(uniself);
- return res;
- }
-#endif
- PyErr_Format(PyExc_TypeError,
-#ifdef Py_USING_UNICODE
- "%s arg must be None, str or unicode",
-#else
- "%s arg must be None or str",
-#endif
- STRIPNAME(striptype));
- return NULL;
- }
-
- return do_strip(self, striptype);
-}
-
-
-PyDoc_STRVAR(strip__doc__,
-"S.strip([chars]) -> string or unicode\n\
-\n\
-Return a copy of the string S with leading and trailing\n\
-whitespace removed.\n\
-If chars is given and not None, remove characters in chars instead.\n\
-If chars is unicode, S will be converted to unicode before stripping");
-
-static PyObject *
-string_strip(PyStringObject *self, PyObject *args)
-{
- if (PyTuple_GET_SIZE(args) == 0)
- return do_strip(self, BOTHSTRIP); /* Common case */
- else
- return do_argstrip(self, BOTHSTRIP, args);
-}
-
-
-PyDoc_STRVAR(lstrip__doc__,
-"S.lstrip([chars]) -> string or unicode\n\
-\n\
-Return a copy of the string S with leading whitespace removed.\n\
-If chars is given and not None, remove characters in chars instead.\n\
-If chars is unicode, S will be converted to unicode before stripping");
-
-static PyObject *
-string_lstrip(PyStringObject *self, PyObject *args)
-{
- if (PyTuple_GET_SIZE(args) == 0)
- return do_strip(self, LEFTSTRIP); /* Common case */
- else
- return do_argstrip(self, LEFTSTRIP, args);
-}
-
-
-PyDoc_STRVAR(rstrip__doc__,
-"S.rstrip([chars]) -> string or unicode\n\
-\n\
-Return a copy of the string S with trailing whitespace removed.\n\
-If chars is given and not None, remove characters in chars instead.\n\
-If chars is unicode, S will be converted to unicode before stripping");
-
-static PyObject *
-string_rstrip(PyStringObject *self, PyObject *args)
-{
- if (PyTuple_GET_SIZE(args) == 0)
- return do_strip(self, RIGHTSTRIP); /* Common case */
- else
- return do_argstrip(self, RIGHTSTRIP, args);
-}
-
-
-PyDoc_STRVAR(lower__doc__,
-"S.lower() -> string\n\
-\n\
-Return a copy of the string S converted to lowercase.");
-
-/* _tolower and _toupper are defined by SUSv2, but they're not ISO C */
-#ifndef _tolower
-#define _tolower tolower
-#endif
-
-static PyObject *
-string_lower(PyStringObject *self)
-{
- char *s;
- Py_ssize_t i, n = PyString_GET_SIZE(self);
- PyObject *newobj;
-
- newobj = PyString_FromStringAndSize(NULL, n);
- if (!newobj)
- return NULL;
-
- s = PyString_AS_STRING(newobj);
-
- Py_MEMCPY(s, PyString_AS_STRING(self), n);
-
- for (i = 0; i < n; i++) {
- int c = Py_CHARMASK(s[i]);
- if (isupper(c))
- s[i] = _tolower(c);
- }
-
- return newobj;
-}
-
-PyDoc_STRVAR(upper__doc__,
-"S.upper() -> string\n\
-\n\
-Return a copy of the string S converted to uppercase.");
-
-#ifndef _toupper
-#define _toupper toupper
-#endif
-
-static PyObject *
-string_upper(PyStringObject *self)
-{
- char *s;
- Py_ssize_t i, n = PyString_GET_SIZE(self);
- PyObject *newobj;
-
- newobj = PyString_FromStringAndSize(NULL, n);
- if (!newobj)
- return NULL;
-
- s = PyString_AS_STRING(newobj);
-
- Py_MEMCPY(s, PyString_AS_STRING(self), n);
-
- for (i = 0; i < n; i++) {
- int c = Py_CHARMASK(s[i]);
- if (islower(c))
- s[i] = _toupper(c);
- }
-
- return newobj;
-}
-
-PyDoc_STRVAR(title__doc__,
-"S.title() -> string\n\
-\n\
-Return a titlecased version of S, i.e. words start with uppercase\n\
-characters, all remaining cased characters have lowercase.");
-
-static PyObject*
-string_title(PyStringObject *self)
-{
- char *s = PyString_AS_STRING(self), *s_new;
- Py_ssize_t i, n = PyString_GET_SIZE(self);
- int previous_is_cased = 0;
- PyObject *newobj;
-
- newobj = PyString_FromStringAndSize(NULL, n);
- if (newobj == NULL)
- return NULL;
- s_new = PyString_AsString(newobj);
- for (i = 0; i < n; i++) {
- int c = Py_CHARMASK(*s++);
- if (islower(c)) {
- if (!previous_is_cased)
- c = toupper(c);
- previous_is_cased = 1;
- } else if (isupper(c)) {
- if (previous_is_cased)
- c = tolower(c);
- previous_is_cased = 1;
- } else
- previous_is_cased = 0;
- *s_new++ = c;
- }
- return newobj;
-}
-
-PyDoc_STRVAR(capitalize__doc__,
-"S.capitalize() -> string\n\
-\n\
-Return a copy of the string S with only its first character\n\
-capitalized.");
-
-static PyObject *
-string_capitalize(PyStringObject *self)
-{
- char *s = PyString_AS_STRING(self), *s_new;
- Py_ssize_t i, n = PyString_GET_SIZE(self);
- PyObject *newobj;
-
- newobj = PyString_FromStringAndSize(NULL, n);
- if (newobj == NULL)
- return NULL;
- s_new = PyString_AsString(newobj);
- if (0 < n) {
- int c = Py_CHARMASK(*s++);
- if (islower(c))
- *s_new = toupper(c);
- else
- *s_new = c;
- s_new++;
- }
- for (i = 1; i < n; i++) {
- int c = Py_CHARMASK(*s++);
- if (isupper(c))
- *s_new = tolower(c);
- else
- *s_new = c;
- s_new++;
- }
- return newobj;
-}
-
-
-PyDoc_STRVAR(count__doc__,
-"S.count(sub[, start[, end]]) -> int\n\
-\n\
-Return the number of non-overlapping occurrences of substring sub in\n\
-string S[start:end]. Optional arguments start and end are interpreted\n\
-as in slice notation.");
-
-static PyObject *
-string_count(PyStringObject *self, PyObject *args)
-{
- PyObject *sub_obj;
- const char *str = PyString_AS_STRING(self), *sub;
- Py_ssize_t sub_len;
- Py_ssize_t start = 0, end = PY_SSIZE_T_MAX;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:count", &sub_obj,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
-
- if (PyString_Check(sub_obj)) {
- sub = PyString_AS_STRING(sub_obj);
- sub_len = PyString_GET_SIZE(sub_obj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(sub_obj)) {
- Py_ssize_t count;
- count = PyUnicode_Count((PyObject *)self, sub_obj, start, end);
- if (count == -1)
- return NULL;
- else
- return PyInt_FromSsize_t(count);
- }
-#endif
- else if (PyObject_AsCharBuffer(sub_obj, &sub, &sub_len))
- return NULL;
-
- string_adjust_indices(&start, &end, PyString_GET_SIZE(self));
-
- return PyInt_FromSsize_t(
- stringlib_count(str + start, end - start, sub, sub_len)
- );
-}
-
-PyDoc_STRVAR(swapcase__doc__,
-"S.swapcase() -> string\n\
-\n\
-Return a copy of the string S with uppercase characters\n\
-converted to lowercase and vice versa.");
-
-static PyObject *
-string_swapcase(PyStringObject *self)
-{
- char *s = PyString_AS_STRING(self), *s_new;
- Py_ssize_t i, n = PyString_GET_SIZE(self);
- PyObject *newobj;
-
- newobj = PyString_FromStringAndSize(NULL, n);
- if (newobj == NULL)
- return NULL;
- s_new = PyString_AsString(newobj);
- for (i = 0; i < n; i++) {
- int c = Py_CHARMASK(*s++);
- if (islower(c)) {
- *s_new = toupper(c);
- }
- else if (isupper(c)) {
- *s_new = tolower(c);
- }
- else
- *s_new = c;
- s_new++;
- }
- return newobj;
-}
-
-
-PyDoc_STRVAR(translate__doc__,
-"S.translate(table [,deletechars]) -> string\n\
-\n\
-Return a copy of the string S, where all characters occurring\n\
-in the optional argument deletechars are removed, and the\n\
-remaining characters have been mapped through the given\n\
-translation table, which must be a string of length 256.");
-
-static PyObject *
-string_translate(PyStringObject *self, PyObject *args)
-{
- register char *input, *output;
- register const char *table;
- register Py_ssize_t i, c, changed = 0;
- PyObject *input_obj = (PyObject*)self;
- const char *table1, *output_start, *del_table=NULL;
- Py_ssize_t inlen, tablen, dellen = 0;
- PyObject *result;
- int trans_table[256];
- PyObject *tableobj, *delobj = NULL;
-
- if (!PyArg_UnpackTuple(args, "translate", 1, 2,
- &tableobj, &delobj))
- return NULL;
-
- if (PyString_Check(tableobj)) {
- table1 = PyString_AS_STRING(tableobj);
- tablen = PyString_GET_SIZE(tableobj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(tableobj)) {
- /* Unicode .translate() does not support the deletechars
- parameter; instead a mapping to None will cause characters
- to be deleted. */
- if (delobj != NULL) {
- PyErr_SetString(PyExc_TypeError,
- "deletions are implemented differently for unicode");
- return NULL;
- }
- return PyUnicode_Translate((PyObject *)self, tableobj, NULL);
- }
-#endif
- else if (PyObject_AsCharBuffer(tableobj, &table1, &tablen))
- return NULL;
-
- if (tablen != 256) {
- PyErr_SetString(PyExc_ValueError,
- "translation table must be 256 characters long");
- return NULL;
- }
-
- if (delobj != NULL) {
- if (PyString_Check(delobj)) {
- del_table = PyString_AS_STRING(delobj);
- dellen = PyString_GET_SIZE(delobj);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(delobj)) {
- PyErr_SetString(PyExc_TypeError,
- "deletions are implemented differently for unicode");
- return NULL;
- }
-#endif
- else if (PyObject_AsCharBuffer(delobj, &del_table, &dellen))
- return NULL;
- }
- else {
- del_table = NULL;
- dellen = 0;
- }
-
- table = table1;
- inlen = PyString_GET_SIZE(input_obj);
- result = PyString_FromStringAndSize((char *)NULL, inlen);
- if (result == NULL)
- return NULL;
- output_start = output = PyString_AsString(result);
- input = PyString_AS_STRING(input_obj);
-
- if (dellen == 0) {
- /* If no deletions are required, use faster code */
- for (i = inlen; --i >= 0; ) {
- c = Py_CHARMASK(*input++);
- if (Py_CHARMASK((*output++ = table[c])) != c)
- changed = 1;
- }
- if (changed || !PyString_CheckExact(input_obj))
- return result;
- Py_DECREF(result);
- Py_INCREF(input_obj);
- return input_obj;
- }
-
- for (i = 0; i < 256; i++)
- trans_table[i] = Py_CHARMASK(table[i]);
-
- for (i = 0; i < dellen; i++)
- trans_table[(int) Py_CHARMASK(del_table[i])] = -1;
-
- for (i = inlen; --i >= 0; ) {
- c = Py_CHARMASK(*input++);
- if (trans_table[c] != -1)
- if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c)
- continue;
- changed = 1;
- }
- if (!changed && PyString_CheckExact(input_obj)) {
- Py_DECREF(result);
- Py_INCREF(input_obj);
- return input_obj;
- }
- /* Fix the size of the resulting string */
- if (inlen > 0)
- _PyString_Resize(&result, output - output_start);
- return result;
-}
-
-
-#define FORWARD 1
-#define REVERSE -1
-
-/* find and count characters and substrings */
-
-#define findchar(target, target_len, c) \
- ((char *)memchr((const void *)(target), c, target_len))
-
-/* String ops must return a string. */
-/* If the object is subclass of string, create a copy */
-Py_LOCAL(PyStringObject *)
-return_self(PyStringObject *self)
-{
- if (PyString_CheckExact(self)) {
- Py_INCREF(self);
- return self;
- }
- return (PyStringObject *)PyString_FromStringAndSize(
- PyString_AS_STRING(self),
- PyString_GET_SIZE(self));
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-countchar(const char *target, int target_len, char c, Py_ssize_t maxcount)
-{
- Py_ssize_t count=0;
- const char *start=target;
- const char *end=target+target_len;
-
- while ( (start=findchar(start, end-start, c)) != NULL ) {
- count++;
- if (count >= maxcount)
- break;
- start += 1;
- }
- return count;
-}
-
-Py_LOCAL(Py_ssize_t)
-findstring(const char *target, Py_ssize_t target_len,
- const char *pattern, Py_ssize_t pattern_len,
- Py_ssize_t start,
- Py_ssize_t end,
- int direction)
-{
- if (start < 0) {
- start += target_len;
- if (start < 0)
- start = 0;
- }
- if (end > target_len) {
- end = target_len;
- } else if (end < 0) {
- end += target_len;
- if (end < 0)
- end = 0;
- }
-
- /* zero-length substrings always match at the first attempt */
- if (pattern_len == 0)
- return (direction > 0) ? start : end;
-
- end -= pattern_len;
-
- if (direction < 0) {
- for (; end >= start; end--)
- if (Py_STRING_MATCH(target, end, pattern, pattern_len))
- return end;
- } else {
- for (; start <= end; start++)
- if (Py_STRING_MATCH(target, start, pattern, pattern_len))
- return start;
- }
- return -1;
-}
-
-Py_LOCAL_INLINE(Py_ssize_t)
-countstring(const char *target, Py_ssize_t target_len,
- const char *pattern, Py_ssize_t pattern_len,
- Py_ssize_t start,
- Py_ssize_t end,
- int direction, Py_ssize_t maxcount)
-{
- Py_ssize_t count=0;
-
- if (start < 0) {
- start += target_len;
- if (start < 0)
- start = 0;
- }
- if (end > target_len) {
- end = target_len;
- } else if (end < 0) {
- end += target_len;
- if (end < 0)
- end = 0;
- }
-
- /* zero-length substrings match everywhere */
- if (pattern_len == 0 || maxcount == 0) {
- if (target_len+1 < maxcount)
- return target_len+1;
- return maxcount;
- }
-
- end -= pattern_len;
- if (direction < 0) {
- for (; (end >= start); end--)
- if (Py_STRING_MATCH(target, end, pattern, pattern_len)) {
- count++;
- if (--maxcount <= 0) break;
- end -= pattern_len-1;
- }
- } else {
- for (; (start <= end); start++)
- if (Py_STRING_MATCH(target, start, pattern, pattern_len)) {
- count++;
- if (--maxcount <= 0)
- break;
- start += pattern_len-1;
- }
- }
- return count;
-}
-
-
-/* Algorithms for different cases of string replacement */
-
-/* len(self)>=1, from="", len(to)>=1, maxcount>=1 */
-Py_LOCAL(PyStringObject *)
-replace_interleave(PyStringObject *self,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, i, product;
- PyStringObject *result;
-
- self_len = PyString_GET_SIZE(self);
-
- /* 1 at the end plus 1 after every character */
- count = self_len+1;
- if (maxcount < count)
- count = maxcount;
-
- /* Check for overflow */
- /* result_len = count * to_len + self_len; */
- product = count * to_len;
- if (product / to_len != count) {
- PyErr_SetString(PyExc_OverflowError,
- "replace string is too long");
- return NULL;
- }
- result_len = product + self_len;
- if (result_len < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "replace string is too long");
- return NULL;
- }
-
- if (! (result = (PyStringObject *)
- PyString_FromStringAndSize(NULL, result_len)) )
- return NULL;
-
- self_s = PyString_AS_STRING(self);
- result_s = PyString_AS_STRING(result);
-
- /* TODO: special case single character, which doesn't need memcpy */
-
- /* Lay the first one down (guaranteed this will occur) */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- count -= 1;
-
- for (i=0; i<count; i++) {
- *result_s++ = *self_s++;
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- }
-
- /* Copy the rest of the original string */
- Py_MEMCPY(result_s, self_s, self_len-i);
-
- return result;
-}
-
-/* Special case for deleting a single character */
-/* len(self)>=1, len(from)==1, to="", maxcount>=1 */
-Py_LOCAL(PyStringObject *)
-replace_delete_single_character(PyStringObject *self,
- char from_c, Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count;
- PyStringObject *result;
-
- self_len = PyString_GET_SIZE(self);
- self_s = PyString_AS_STRING(self);
-
- count = countchar(self_s, self_len, from_c, maxcount);
- if (count == 0) {
- return return_self(self);
- }
-
- result_len = self_len - count; /* from_len == 1 */
- assert(result_len>=0);
-
- if ( (result = (PyStringObject *)
- PyString_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyString_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- start = next+1;
- }
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-/* len(self)>=1, len(from)>=2, to="", maxcount>=1 */
-
-Py_LOCAL(PyStringObject *)
-replace_delete_substring(PyStringObject *self,
- const char *from_s, Py_ssize_t from_len,
- Py_ssize_t maxcount) {
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, offset;
- PyStringObject *result;
-
- self_len = PyString_GET_SIZE(self);
- self_s = PyString_AS_STRING(self);
-
- count = countstring(self_s, self_len,
- from_s, from_len,
- 0, self_len, 1,
- maxcount);
-
- if (count == 0) {
- /* no matches */
- return return_self(self);
- }
-
- result_len = self_len - (count * from_len);
- assert (result_len>=0);
-
- if ( (result = (PyStringObject *)
- PyString_FromStringAndSize(NULL, result_len)) == NULL )
- return NULL;
-
- result_s = PyString_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- offset = findstring(start, end-start,
- from_s, from_len,
- 0, end-start, FORWARD);
- if (offset == -1)
- break;
- next = start + offset;
-
- Py_MEMCPY(result_s, start, next-start);
-
- result_s += (next-start);
- start = next+from_len;
- }
- Py_MEMCPY(result_s, start, end-start);
- return result;
-}
-
-/* len(self)>=1, len(from)==len(to)==1, maxcount>=1 */
-Py_LOCAL(PyStringObject *)
-replace_single_character_in_place(PyStringObject *self,
- char from_c, char to_c,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s, *start, *end, *next;
- Py_ssize_t self_len;
- PyStringObject *result;
-
- /* The result string will be the same size */
- self_s = PyString_AS_STRING(self);
- self_len = PyString_GET_SIZE(self);
-
- next = findchar(self_s, self_len, from_c);
-
- if (next == NULL) {
- /* No matches; return the original string */
- return return_self(self);
- }
-
- /* Need to make a new string */
- result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);
- if (result == NULL)
- return NULL;
- result_s = PyString_AS_STRING(result);
- Py_MEMCPY(result_s, self_s, self_len);
-
- /* change everything in-place, starting with this one */
- start = result_s + (next-self_s);
- *start = to_c;
- start++;
- end = result_s + self_len;
-
- while (--maxcount > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
- *next = to_c;
- start = next+1;
- }
-
- return result;
-}
-
-/* len(self)>=1, len(from)==len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyStringObject *)
-replace_substring_in_place(PyStringObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *result_s, *start, *end;
- char *self_s;
- Py_ssize_t self_len, offset;
- PyStringObject *result;
-
- /* The result string will be the same size */
-
- self_s = PyString_AS_STRING(self);
- self_len = PyString_GET_SIZE(self);
-
- offset = findstring(self_s, self_len,
- from_s, from_len,
- 0, self_len, FORWARD);
- if (offset == -1) {
- /* No matches; return the original string */
- return return_self(self);
- }
-
- /* Need to make a new string */
- result = (PyStringObject *) PyString_FromStringAndSize(NULL, self_len);
- if (result == NULL)
- return NULL;
- result_s = PyString_AS_STRING(result);
- Py_MEMCPY(result_s, self_s, self_len);
-
- /* change everything in-place, starting with this one */
- start = result_s + offset;
- Py_MEMCPY(start, to_s, from_len);
- start += from_len;
- end = result_s + self_len;
-
- while ( --maxcount > 0) {
- offset = findstring(start, end-start,
- from_s, from_len,
- 0, end-start, FORWARD);
- if (offset==-1)
- break;
- Py_MEMCPY(start+offset, to_s, from_len);
- start += offset+from_len;
- }
-
- return result;
-}
-
-/* len(self)>=1, len(from)==1, len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyStringObject *)
-replace_single_character(PyStringObject *self,
- char from_c,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, product;
- PyStringObject *result;
-
- self_s = PyString_AS_STRING(self);
- self_len = PyString_GET_SIZE(self);
-
- count = countchar(self_s, self_len, from_c, maxcount);
- if (count == 0) {
- /* no matches, return unchanged */
- return return_self(self);
- }
-
- /* use the difference between current and new, hence the "-1" */
- /* result_len = self_len + count * (to_len-1) */
- product = count * (to_len-1);
- if (product / (to_len-1) != count) {
- PyErr_SetString(PyExc_OverflowError, "replace string is too long");
- return NULL;
- }
- result_len = self_len + product;
- if (result_len < 0) {
- PyErr_SetString(PyExc_OverflowError, "replace string is too long");
- return NULL;
- }
-
- if ( (result = (PyStringObject *)
- PyString_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyString_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- next = findchar(start, end-start, from_c);
- if (next == NULL)
- break;
-
- if (next == start) {
- /* replace with the 'to' */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start += 1;
- } else {
- /* copy the unchanged old then the 'to' */
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start = next+1;
- }
- }
- /* Copy the remainder of the remaining string */
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-/* len(self)>=1, len(from)>=2, len(to)>=2, maxcount>=1 */
-Py_LOCAL(PyStringObject *)
-replace_substring(PyStringObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount) {
- char *self_s, *result_s;
- char *start, *next, *end;
- Py_ssize_t self_len, result_len;
- Py_ssize_t count, offset, product;
- PyStringObject *result;
-
- self_s = PyString_AS_STRING(self);
- self_len = PyString_GET_SIZE(self);
-
- count = countstring(self_s, self_len,
- from_s, from_len,
- 0, self_len, FORWARD, maxcount);
- if (count == 0) {
- /* no matches, return unchanged */
- return return_self(self);
- }
-
- /* Check for overflow */
- /* result_len = self_len + count * (to_len-from_len) */
- product = count * (to_len-from_len);
- if (product / (to_len-from_len) != count) {
- PyErr_SetString(PyExc_OverflowError, "replace string is too long");
- return NULL;
- }
- result_len = self_len + product;
- if (result_len < 0) {
- PyErr_SetString(PyExc_OverflowError, "replace string is too long");
- return NULL;
- }
-
- if ( (result = (PyStringObject *)
- PyString_FromStringAndSize(NULL, result_len)) == NULL)
- return NULL;
- result_s = PyString_AS_STRING(result);
-
- start = self_s;
- end = self_s + self_len;
- while (count-- > 0) {
- offset = findstring(start, end-start,
- from_s, from_len,
- 0, end-start, FORWARD);
- if (offset == -1)
- break;
- next = start+offset;
- if (next == start) {
- /* replace with the 'to' */
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start += from_len;
- } else {
- /* copy the unchanged old then the 'to' */
- Py_MEMCPY(result_s, start, next-start);
- result_s += (next-start);
- Py_MEMCPY(result_s, to_s, to_len);
- result_s += to_len;
- start = next+from_len;
- }
- }
- /* Copy the remainder of the remaining string */
- Py_MEMCPY(result_s, start, end-start);
-
- return result;
-}
-
-
-Py_LOCAL(PyStringObject *)
-replace(PyStringObject *self,
- const char *from_s, Py_ssize_t from_len,
- const char *to_s, Py_ssize_t to_len,
- Py_ssize_t maxcount)
-{
- if (maxcount < 0) {
- maxcount = PY_SSIZE_T_MAX;
- } else if (maxcount == 0 || PyString_GET_SIZE(self) == 0) {
- /* nothing to do; return the original string */
- return return_self(self);
- }
-
- if (maxcount == 0 ||
- (from_len == 0 && to_len == 0)) {
- /* nothing to do; return the original string */
- return return_self(self);
- }
-
- /* Handle zero-length special cases */
-
- if (from_len == 0) {
- /* insert the 'to' string everywhere. */
- /* >>> "Python".replace("", ".") */
- /* '.P.y.t.h.o.n.' */
- return replace_interleave(self, to_s, to_len, maxcount);
- }
-
- /* Except for "".replace("", "A") == "A" there is no way beyond this */
- /* point for an empty self string to generate a non-empty string */
- /* Special case so the remaining code always gets a non-empty string */
- if (PyString_GET_SIZE(self) == 0) {
- return return_self(self);
- }
-
- if (to_len == 0) {
- /* delete all occurances of 'from' string */
- if (from_len == 1) {
- return replace_delete_single_character(
- self, from_s[0], maxcount);
- } else {
- return replace_delete_substring(self, from_s, from_len, maxcount);
- }
- }
-
- /* Handle special case where both strings have the same length */
-
- if (from_len == to_len) {
- if (from_len == 1) {
- return replace_single_character_in_place(
- self,
- from_s[0],
- to_s[0],
- maxcount);
- } else {
- return replace_substring_in_place(
- self, from_s, from_len, to_s, to_len, maxcount);
- }
- }
-
- /* Otherwise use the more generic algorithms */
- if (from_len == 1) {
- return replace_single_character(self, from_s[0],
- to_s, to_len, maxcount);
- } else {
- /* len('from')>=2, len('to')>=1 */
- return replace_substring(self, from_s, from_len, to_s, to_len, maxcount);
- }
-}
-
-PyDoc_STRVAR(replace__doc__,
-"S.replace (old, new[, count]) -> string\n\
-\n\
-Return a copy of string S with all occurrences of substring\n\
-old replaced by new. If the optional argument count is\n\
-given, only the first count occurrences are replaced.");
-
-static PyObject *
-string_replace(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t count = -1;
- PyObject *from, *to;
- const char *from_s, *to_s;
- Py_ssize_t from_len, to_len;
-
- if (!PyArg_ParseTuple(args, "OO|n:replace", &from, &to, &count))
- return NULL;
-
- if (PyString_Check(from)) {
- from_s = PyString_AS_STRING(from);
- from_len = PyString_GET_SIZE(from);
- }
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(from))
- return PyUnicode_Replace((PyObject *)self,
- from, to, count);
-#endif
- else if (PyObject_AsCharBuffer(from, &from_s, &from_len))
- return NULL;
-
- if (PyString_Check(to)) {
- to_s = PyString_AS_STRING(to);
- to_len = PyString_GET_SIZE(to);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(to))
- return PyUnicode_Replace((PyObject *)self,
- from, to, count);
-#endif
- else if (PyObject_AsCharBuffer(to, &to_s, &to_len))
- return NULL;
-
- return (PyObject *)replace((PyStringObject *) self,
- from_s, from_len,
- to_s, to_len, count);
-}
-
-/** End DALKE **/
-
-/* Matches the end (direction >= 0) or start (direction < 0) of self
- * against substr, using the start and end arguments. Returns
- * -1 on error, 0 if not found and 1 if found.
- */
-Py_LOCAL(int)
-_string_tailmatch(PyStringObject *self, PyObject *substr, Py_ssize_t start,
- Py_ssize_t end, int direction)
-{
- Py_ssize_t len = PyString_GET_SIZE(self);
- Py_ssize_t slen;
- const char* sub;
- const char* str;
-
- if (PyString_Check(substr)) {
- sub = PyString_AS_STRING(substr);
- slen = PyString_GET_SIZE(substr);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(substr))
- return PyUnicode_Tailmatch((PyObject *)self,
- substr, start, end, direction);
-#endif
- else if (PyObject_AsCharBuffer(substr, &sub, &slen))
- return -1;
- str = PyString_AS_STRING(self);
-
- string_adjust_indices(&start, &end, len);
-
- if (direction < 0) {
- /* startswith */
- if (start+slen > len)
- return 0;
- } else {
- /* endswith */
- if (end-start < slen || start > len)
- return 0;
-
- if (end-slen > start)
- start = end - slen;
- }
- if (end-start >= slen)
- return ! memcmp(str+start, sub, slen);
- return 0;
-}
-
-
-PyDoc_STRVAR(startswith__doc__,
-"S.startswith(prefix[, start[, end]]) -> bool\n\
-\n\
-Return True if S starts with the specified prefix, False otherwise.\n\
-With optional start, test S beginning at that position.\n\
-With optional end, stop comparing S at that position.\n\
-prefix can also be a tuple of strings to try.");
-
-static PyObject *
-string_startswith(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- PyObject *subobj;
- int result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:startswith", &subobj,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- result = _string_tailmatch(self,
- PyTuple_GET_ITEM(subobj, i),
- start, end, -1);
- if (result == -1)
- return NULL;
- else if (result) {
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- }
- result = _string_tailmatch(self, subobj, start, end, -1);
- if (result == -1)
- return NULL;
- else
- return PyBool_FromLong(result);
-}
-
-
-PyDoc_STRVAR(endswith__doc__,
-"S.endswith(suffix[, start[, end]]) -> bool\n\
-\n\
-Return True if S ends with the specified suffix, False otherwise.\n\
-With optional start, test S beginning at that position.\n\
-With optional end, stop comparing S at that position.\n\
-suffix can also be a tuple of strings to try.");
-
-static PyObject *
-string_endswith(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- PyObject *subobj;
- int result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:endswith", &subobj,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- result = _string_tailmatch(self,
- PyTuple_GET_ITEM(subobj, i),
- start, end, +1);
- if (result == -1)
- return NULL;
- else if (result) {
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- }
- result = _string_tailmatch(self, subobj, start, end, +1);
- if (result == -1)
- return NULL;
- else
- return PyBool_FromLong(result);
-}
-
-
-PyDoc_STRVAR(encode__doc__,
-"S.encode([encoding[,errors]]) -> object\n\
-\n\
-Encodes S using the codec registered for encoding. encoding defaults\n\
-to the default encoding. errors may be given to set a different error\n\
-handling scheme. Default is 'strict' meaning that encoding errors raise\n\
-a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and\n\
-'xmlcharrefreplace' as well as any other name registered with\n\
-codecs.register_error that is able to handle UnicodeEncodeErrors.");
-
-static PyObject *
-string_encode(PyStringObject *self, PyObject *args)
-{
- char *encoding = NULL;
- char *errors = NULL;
- PyObject *v;
-
- if (!PyArg_ParseTuple(args, "|ss:encode", &encoding, &errors))
- return NULL;
- v = PyString_AsEncodedObject((PyObject *)self, encoding, errors);
- if (v == NULL)
- goto onError;
- if (!PyString_Check(v) && !PyUnicode_Check(v)) {
- PyErr_Format(PyExc_TypeError,
- "encoder did not return a string/unicode object "
- "(type=%.400s)",
- v->ob_type->tp_name);
- Py_DECREF(v);
- return NULL;
- }
- return v;
-
- onError:
- return NULL;
-}
-
-
-PyDoc_STRVAR(decode__doc__,
-"S.decode([encoding[,errors]]) -> object\n\
-\n\
-Decodes S using the codec registered for encoding. encoding defaults\n\
-to the default encoding. errors may be given to set a different error\n\
-handling scheme. Default is 'strict' meaning that encoding errors raise\n\
-a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\
-as well as any other name registerd with codecs.register_error that is\n\
-able to handle UnicodeDecodeErrors.");
-
-static PyObject *
-string_decode(PyStringObject *self, PyObject *args)
-{
- char *encoding = NULL;
- char *errors = NULL;
- PyObject *v;
-
- if (!PyArg_ParseTuple(args, "|ss:decode", &encoding, &errors))
- return NULL;
- v = PyString_AsDecodedObject((PyObject *)self, encoding, errors);
- if (v == NULL)
- goto onError;
- if (!PyString_Check(v) && !PyUnicode_Check(v)) {
- PyErr_Format(PyExc_TypeError,
- "decoder did not return a string/unicode object "
- "(type=%.400s)",
- v->ob_type->tp_name);
- Py_DECREF(v);
- return NULL;
- }
- return v;
-
- onError:
- return NULL;
-}
-
-
-PyDoc_STRVAR(expandtabs__doc__,
-"S.expandtabs([tabsize]) -> string\n\
-\n\
-Return a copy of S where all tab characters are expanded using spaces.\n\
-If tabsize is not given, a tab size of 8 characters is assumed.");
-
-static PyObject*
-string_expandtabs(PyStringObject *self, PyObject *args)
-{
- const char *e, *p;
- char *q;
- Py_ssize_t i, j;
- PyObject *u;
- int tabsize = 8;
-
- if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
- return NULL;
-
- /* First pass: determine size of output string */
- i = j = 0;
- e = PyString_AS_STRING(self) + PyString_GET_SIZE(self);
- for (p = PyString_AS_STRING(self); p < e; p++)
- if (*p == '\t') {
- if (tabsize > 0)
- j += tabsize - (j % tabsize);
- }
- else {
- j++;
- if (*p == '\n' || *p == '\r') {
- i += j;
- j = 0;
- }
- }
-
- /* Second pass: create output string and fill it */
- u = PyString_FromStringAndSize(NULL, i + j);
- if (!u)
- return NULL;
-
- j = 0;
- q = PyString_AS_STRING(u);
-
- for (p = PyString_AS_STRING(self); p < e; p++)
- if (*p == '\t') {
- if (tabsize > 0) {
- i = tabsize - (j % tabsize);
- j += i;
- while (i--)
- *q++ = ' ';
- }
- }
- else {
- j++;
- *q++ = *p;
- if (*p == '\n' || *p == '\r')
- j = 0;
- }
-
- return u;
-}
-
-Py_LOCAL_INLINE(PyObject *)
-pad(PyStringObject *self, Py_ssize_t left, Py_ssize_t right, char fill)
-{
- PyObject *u;
-
- if (left < 0)
- left = 0;
- if (right < 0)
- right = 0;
-
- if (left == 0 && right == 0 && PyString_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject *)self;
- }
-
- u = PyString_FromStringAndSize(NULL,
- left + PyString_GET_SIZE(self) + right);
- if (u) {
- if (left)
- memset(PyString_AS_STRING(u), fill, left);
- Py_MEMCPY(PyString_AS_STRING(u) + left,
- PyString_AS_STRING(self),
- PyString_GET_SIZE(self));
- if (right)
- memset(PyString_AS_STRING(u) + left + PyString_GET_SIZE(self),
- fill, right);
- }
-
- return u;
-}
-
-PyDoc_STRVAR(ljust__doc__,
-"S.ljust(width[, fillchar]) -> string\n"
-"\n"
-"Return S left justified in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space).");
-
-static PyObject *
-string_ljust(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t width;
- char fillchar = ' ';
-
- if (!PyArg_ParseTuple(args, "n|c:ljust", &width, &fillchar))
- return NULL;
-
- if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
-
- return pad(self, 0, width - PyString_GET_SIZE(self), fillchar);
-}
-
-
-PyDoc_STRVAR(rjust__doc__,
-"S.rjust(width[, fillchar]) -> string\n"
-"\n"
-"Return S right justified in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space)");
-
-static PyObject *
-string_rjust(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t width;
- char fillchar = ' ';
-
- if (!PyArg_ParseTuple(args, "n|c:rjust", &width, &fillchar))
- return NULL;
-
- if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
-
- return pad(self, width - PyString_GET_SIZE(self), 0, fillchar);
-}
-
-
-PyDoc_STRVAR(center__doc__,
-"S.center(width[, fillchar]) -> string\n"
-"\n"
-"Return S centered in a string of length width. Padding is\n"
-"done using the specified fill character (default is a space)");
-
-static PyObject *
-string_center(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t marg, left;
- Py_ssize_t width;
- char fillchar = ' ';
-
- if (!PyArg_ParseTuple(args, "n|c:center", &width, &fillchar))
- return NULL;
-
- if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
-
- marg = width - PyString_GET_SIZE(self);
- left = marg / 2 + (marg & width & 1);
-
- return pad(self, left, marg - left, fillchar);
-}
-
-PyDoc_STRVAR(zfill__doc__,
-"S.zfill(width) -> string\n"
-"\n"
-"Pad a numeric string S with zeros on the left, to fill a field\n"
-"of the specified width. The string S is never truncated.");
-
-static PyObject *
-string_zfill(PyStringObject *self, PyObject *args)
-{
- Py_ssize_t fill;
- PyObject *s;
- char *p;
- Py_ssize_t width;
-
- if (!PyArg_ParseTuple(args, "n:zfill", &width))
- return NULL;
-
- if (PyString_GET_SIZE(self) >= width) {
- if (PyString_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
- else
- return PyString_FromStringAndSize(
- PyString_AS_STRING(self),
- PyString_GET_SIZE(self)
- );
- }
-
- fill = width - PyString_GET_SIZE(self);
-
- s = pad(self, fill, 0, '0');
-
- if (s == NULL)
- return NULL;
-
- p = PyString_AS_STRING(s);
- if (p[fill] == '+' || p[fill] == '-') {
- /* move sign to beginning of string */
- p[0] = p[fill];
- p[fill] = '0';
- }
-
- return (PyObject*) s;
-}
-
-PyDoc_STRVAR(isspace__doc__,
-"S.isspace() -> bool\n\
-\n\
-Return True if all characters in S are whitespace\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-string_isspace(PyStringObject *self)
-{
- register const unsigned char *p
- = (unsigned char *) PyString_AS_STRING(self);
- register const unsigned char *e;
-
- /* Shortcut for single character strings */
- if (PyString_GET_SIZE(self) == 1 &&
- isspace(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyString_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyString_GET_SIZE(self);
- for (; p < e; p++) {
- if (!isspace(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-
-PyDoc_STRVAR(isalpha__doc__,
-"S.isalpha() -> bool\n\
-\n\
-Return True if all characters in S are alphabetic\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-string_isalpha(PyStringObject *self)
-{
- register const unsigned char *p
- = (unsigned char *) PyString_AS_STRING(self);
- register const unsigned char *e;
-
- /* Shortcut for single character strings */
- if (PyString_GET_SIZE(self) == 1 &&
- isalpha(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyString_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyString_GET_SIZE(self);
- for (; p < e; p++) {
- if (!isalpha(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-
-PyDoc_STRVAR(isalnum__doc__,
-"S.isalnum() -> bool\n\
-\n\
-Return True if all characters in S are alphanumeric\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-string_isalnum(PyStringObject *self)
-{
- register const unsigned char *p
- = (unsigned char *) PyString_AS_STRING(self);
- register const unsigned char *e;
-
- /* Shortcut for single character strings */
- if (PyString_GET_SIZE(self) == 1 &&
- isalnum(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyString_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyString_GET_SIZE(self);
- for (; p < e; p++) {
- if (!isalnum(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-
-PyDoc_STRVAR(isdigit__doc__,
-"S.isdigit() -> bool\n\
-\n\
-Return True if all characters in S are digits\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-string_isdigit(PyStringObject *self)
-{
- register const unsigned char *p
- = (unsigned char *) PyString_AS_STRING(self);
- register const unsigned char *e;
-
- /* Shortcut for single character strings */
- if (PyString_GET_SIZE(self) == 1 &&
- isdigit(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyString_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyString_GET_SIZE(self);
- for (; p < e; p++) {
- if (!isdigit(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-
-PyDoc_STRVAR(islower__doc__,
-"S.islower() -> bool\n\
-\n\
-Return True if all cased characters in S are lowercase and there is\n\
-at least one cased character in S, False otherwise.");
-
-static PyObject*
-string_islower(PyStringObject *self)
-{
- register const unsigned char *p
- = (unsigned char *) PyString_AS_STRING(self);
- register const unsigned char *e;
- int cased;
-
- /* Shortcut for single character strings */
- if (PyString_GET_SIZE(self) == 1)
- return PyBool_FromLong(islower(*p) != 0);
-
- /* Special case for empty strings */
- if (PyString_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyString_GET_SIZE(self);
- cased = 0;
- for (; p < e; p++) {
- if (isupper(*p))
- return PyBool_FromLong(0);
- else if (!cased && islower(*p))
- cased = 1;
- }
- return PyBool_FromLong(cased);
-}
-
-
-PyDoc_STRVAR(isupper__doc__,
-"S.isupper() -> bool\n\
-\n\
-Return True if all cased characters in S are uppercase and there is\n\
-at least one cased character in S, False otherwise.");
-
-static PyObject*
-string_isupper(PyStringObject *self)
-{
- register const unsigned char *p
- = (unsigned char *) PyString_AS_STRING(self);
- register const unsigned char *e;
- int cased;
-
- /* Shortcut for single character strings */
- if (PyString_GET_SIZE(self) == 1)
- return PyBool_FromLong(isupper(*p) != 0);
-
- /* Special case for empty strings */
- if (PyString_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyString_GET_SIZE(self);
- cased = 0;
- for (; p < e; p++) {
- if (islower(*p))
- return PyBool_FromLong(0);
- else if (!cased && isupper(*p))
- cased = 1;
- }
- return PyBool_FromLong(cased);
-}
-
-
-PyDoc_STRVAR(istitle__doc__,
-"S.istitle() -> bool\n\
-\n\
-Return True if S is a titlecased string and there is at least one\n\
-character in S, i.e. uppercase characters may only follow uncased\n\
-characters and lowercase characters only cased ones. Return False\n\
-otherwise.");
-
-static PyObject*
-string_istitle(PyStringObject *self, PyObject *uncased)
-{
- register const unsigned char *p
- = (unsigned char *) PyString_AS_STRING(self);
- register const unsigned char *e;
- int cased, previous_is_cased;
-
- /* Shortcut for single character strings */
- if (PyString_GET_SIZE(self) == 1)
- return PyBool_FromLong(isupper(*p) != 0);
-
- /* Special case for empty strings */
- if (PyString_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyString_GET_SIZE(self);
- cased = 0;
- previous_is_cased = 0;
- for (; p < e; p++) {
- register const unsigned char ch = *p;
-
- if (isupper(ch)) {
- if (previous_is_cased)
- return PyBool_FromLong(0);
- previous_is_cased = 1;
- cased = 1;
- }
- else if (islower(ch)) {
- if (!previous_is_cased)
- return PyBool_FromLong(0);
- previous_is_cased = 1;
- cased = 1;
- }
- else
- previous_is_cased = 0;
- }
- return PyBool_FromLong(cased);
-}
-
-
-PyDoc_STRVAR(splitlines__doc__,
-"S.splitlines([keepends]) -> list of strings\n\
-\n\
-Return a list of the lines in S, breaking at line boundaries.\n\
-Line breaks are not included in the resulting list unless keepends\n\
-is given and true.");
-
-static PyObject*
-string_splitlines(PyStringObject *self, PyObject *args)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len;
- int keepends = 0;
- PyObject *list;
- PyObject *str;
- char *data;
-
- if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends))
- return NULL;
-
- data = PyString_AS_STRING(self);
- len = PyString_GET_SIZE(self);
-
- /* This does not use the preallocated list because splitlines is
- usually run with hundreds of newlines. The overhead of
- switching between PyList_SET_ITEM and append causes about a
- 2-3% slowdown for that common case. A smarter implementation
- could move the if check out, so the SET_ITEMs are done first
- and the appends only done when the prealloc buffer is full.
- That's too much work for little gain.*/
-
- list = PyList_New(0);
- if (!list)
- goto onError;
-
- for (i = j = 0; i < len; ) {
- Py_ssize_t eol;
-
- /* Find a line and append it */
- while (i < len && data[i] != '\n' && data[i] != '\r')
- i++;
-
- /* Skip the line break reading CRLF as one line break */
- eol = i;
- if (i < len) {
- if (data[i] == '\r' && i + 1 < len &&
- data[i+1] == '\n')
- i += 2;
- else
- i++;
- if (keepends)
- eol = i;
- }
- SPLIT_APPEND(data, j, eol);
- j = i;
- }
- if (j < len) {
- SPLIT_APPEND(data, j, len);
- }
-
- return list;
-
- onError:
- Py_XDECREF(list);
- return NULL;
-}
-
-#undef SPLIT_APPEND
-#undef SPLIT_ADD
-#undef MAX_PREALLOC
-#undef PREALLOC_SIZE
-
-static PyObject *
-string_getnewargs(PyStringObject *v)
-{
- return Py_BuildValue("(s#)", v->ob_sval, v->ob_size);
-}
-
-
-static PyMethodDef
-string_methods[] = {
- /* Counterparts of the obsolete stropmodule functions; except
- string.maketrans(). */
- {"join", (PyCFunction)string_join, METH_O, join__doc__},
- {"split", (PyCFunction)string_split, METH_VARARGS, split__doc__},
- {"rsplit", (PyCFunction)string_rsplit, METH_VARARGS, rsplit__doc__},
- {"lower", (PyCFunction)string_lower, METH_NOARGS, lower__doc__},
- {"upper", (PyCFunction)string_upper, METH_NOARGS, upper__doc__},
- {"islower", (PyCFunction)string_islower, METH_NOARGS, islower__doc__},
- {"isupper", (PyCFunction)string_isupper, METH_NOARGS, isupper__doc__},
- {"isspace", (PyCFunction)string_isspace, METH_NOARGS, isspace__doc__},
- {"isdigit", (PyCFunction)string_isdigit, METH_NOARGS, isdigit__doc__},
- {"istitle", (PyCFunction)string_istitle, METH_NOARGS, istitle__doc__},
- {"isalpha", (PyCFunction)string_isalpha, METH_NOARGS, isalpha__doc__},
- {"isalnum", (PyCFunction)string_isalnum, METH_NOARGS, isalnum__doc__},
- {"capitalize", (PyCFunction)string_capitalize, METH_NOARGS,
- capitalize__doc__},
- {"count", (PyCFunction)string_count, METH_VARARGS, count__doc__},
- {"endswith", (PyCFunction)string_endswith, METH_VARARGS,
- endswith__doc__},
- {"partition", (PyCFunction)string_partition, METH_O, partition__doc__},
- {"find", (PyCFunction)string_find, METH_VARARGS, find__doc__},
- {"index", (PyCFunction)string_index, METH_VARARGS, index__doc__},
- {"lstrip", (PyCFunction)string_lstrip, METH_VARARGS, lstrip__doc__},
- {"replace", (PyCFunction)string_replace, METH_VARARGS, replace__doc__},
- {"rfind", (PyCFunction)string_rfind, METH_VARARGS, rfind__doc__},
- {"rindex", (PyCFunction)string_rindex, METH_VARARGS, rindex__doc__},
- {"rstrip", (PyCFunction)string_rstrip, METH_VARARGS, rstrip__doc__},
- {"rpartition", (PyCFunction)string_rpartition, METH_O,
- rpartition__doc__},
- {"startswith", (PyCFunction)string_startswith, METH_VARARGS,
- startswith__doc__},
- {"strip", (PyCFunction)string_strip, METH_VARARGS, strip__doc__},
- {"swapcase", (PyCFunction)string_swapcase, METH_NOARGS,
- swapcase__doc__},
- {"translate", (PyCFunction)string_translate, METH_VARARGS,
- translate__doc__},
- {"title", (PyCFunction)string_title, METH_NOARGS, title__doc__},
- {"ljust", (PyCFunction)string_ljust, METH_VARARGS, ljust__doc__},
- {"rjust", (PyCFunction)string_rjust, METH_VARARGS, rjust__doc__},
- {"center", (PyCFunction)string_center, METH_VARARGS, center__doc__},
- {"zfill", (PyCFunction)string_zfill, METH_VARARGS, zfill__doc__},
- {"encode", (PyCFunction)string_encode, METH_VARARGS, encode__doc__},
- {"decode", (PyCFunction)string_decode, METH_VARARGS, decode__doc__},
- {"expandtabs", (PyCFunction)string_expandtabs, METH_VARARGS,
- expandtabs__doc__},
- {"splitlines", (PyCFunction)string_splitlines, METH_VARARGS,
- splitlines__doc__},
- {"__getnewargs__", (PyCFunction)string_getnewargs, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyObject *
-str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyObject *
-string_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *x = NULL;
- static char *kwlist[] = {"object", 0};
-
- if (type != &PyString_Type)
- return str_subtype_new(type, args, kwds);
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:str", kwlist, &x))
- return NULL;
- if (x == NULL)
- return PyString_FromString("");
- return PyObject_Str(x);
-}
-
-static PyObject *
-str_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *tmp, *pnew;
- Py_ssize_t n;
-
- assert(PyType_IsSubtype(type, &PyString_Type));
- tmp = string_new(&PyString_Type, args, kwds);
- if (tmp == NULL)
- return NULL;
- assert(PyString_CheckExact(tmp));
- n = PyString_GET_SIZE(tmp);
- pnew = type->tp_alloc(type, n);
- if (pnew != NULL) {
- Py_MEMCPY(PyString_AS_STRING(pnew), PyString_AS_STRING(tmp), n+1);
- ((PyStringObject *)pnew)->ob_shash =
- ((PyStringObject *)tmp)->ob_shash;
- ((PyStringObject *)pnew)->ob_sstate = SSTATE_NOT_INTERNED;
- }
- Py_DECREF(tmp);
- return pnew;
-}
-
-static PyObject *
-basestring_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyErr_SetString(PyExc_TypeError,
- "The basestring type cannot be instantiated");
- return NULL;
-}
-
-static PyObject *
-string_mod(PyObject *v, PyObject *w)
-{
- if (!PyString_Check(v)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return PyString_Format(v, w);
-}
-
-PyDoc_STRVAR(basestring_doc,
-"Type basestring cannot be instantiated; it is the base for str and unicode.");
-
-static PyNumberMethods string_as_number = {
- 0, /*nb_add*/
- 0, /*nb_subtract*/
- 0, /*nb_multiply*/
- 0, /*nb_divide*/
- string_mod, /*nb_remainder*/
-};
-
-
-PyTypeObject PyBaseString_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "basestring",
- 0,
- 0,
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- basestring_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &PyBaseObject_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- basestring_new, /* tp_new */
- 0, /* tp_free */
-};
-
-PyDoc_STRVAR(string_doc,
-"str(object) -> string\n\
-\n\
-Return a nice string representation of the object.\n\
-If the argument is a string, the return value is the same object.");
-
-PyTypeObject PyString_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "str",
- sizeof(PyStringObject),
- sizeof(char),
- string_dealloc, /* tp_dealloc */
- (printfunc)string_print, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- string_repr, /* tp_repr */
- &string_as_number, /* tp_as_number */
- &string_as_sequence, /* tp_as_sequence */
- &string_as_mapping, /* tp_as_mapping */
- (hashfunc)string_hash, /* tp_hash */
- 0, /* tp_call */
- string_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- &string_as_buffer, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- string_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- (richcmpfunc)string_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- string_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &PyBaseString_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- string_new, /* tp_new */
- PyObject_Del, /* tp_free */
-};
-
-void
-PyString_Concat(register PyObject **pv, register PyObject *w)
-{
- register PyObject *v;
- if (*pv == NULL)
- return;
- if (w == NULL || !PyString_Check(*pv)) {
- Py_DECREF(*pv);
- *pv = NULL;
- return;
- }
- v = string_concat((PyStringObject *) *pv, w);
- Py_DECREF(*pv);
- *pv = v;
-}
-
-void
-PyString_ConcatAndDel(register PyObject **pv, register PyObject *w)
-{
- PyString_Concat(pv, w);
- Py_XDECREF(w);
-}
-
-
-/* The following function breaks the notion that strings are immutable:
- it changes the size of a string. We get away with this only if there
- is only one module referencing the object. You can also think of it
- as creating a new string object and destroying the old one, only
- more efficiently. In any case, don't use this if the string may
- already be known to some other part of the code...
- Note that if there's not enough memory to resize the string, the original
- string object at *pv is deallocated, *pv is set to NULL, an "out of
- memory" exception is set, and -1 is returned. Else (on success) 0 is
- returned, and the value in *pv may or may not be the same as on input.
- As always, an extra byte is allocated for a trailing \0 byte (newsize
- does *not* include that), and a trailing \0 byte is stored.
-*/
-
-int
-_PyString_Resize(PyObject **pv, Py_ssize_t newsize)
-{
- register PyObject *v;
- register PyStringObject *sv;
- v = *pv;
- if (!PyString_Check(v) || v->ob_refcnt != 1 || newsize < 0 ||
- PyString_CHECK_INTERNED(v)) {
- *pv = 0;
- Py_DECREF(v);
- PyErr_BadInternalCall();
- return -1;
- }
- /* XXX UNREF/NEWREF interface should be more symmetrical */
- _Py_DEC_REFTOTAL;
- _Py_ForgetReference(v);
- *pv = (PyObject *)
- PyObject_REALLOC((char *)v, sizeof(PyStringObject) + newsize);
- if (*pv == NULL) {
- PyObject_Del(v);
- PyErr_NoMemory();
- return -1;
- }
- _Py_NewReference(*pv);
- sv = (PyStringObject *) *pv;
- sv->ob_size = newsize;
- sv->ob_sval[newsize] = '\0';
- sv->ob_shash = -1; /* invalidate cached hash value */
- return 0;
-}
-
-/* Helpers for formatstring */
-
-Py_LOCAL_INLINE(PyObject *)
-getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)
-{
- Py_ssize_t argidx = *p_argidx;
- if (argidx < arglen) {
- (*p_argidx)++;
- if (arglen < 0)
- return args;
- else
- return PyTuple_GetItem(args, argidx);
- }
- PyErr_SetString(PyExc_TypeError,
- "not enough arguments for format string");
- return NULL;
-}
-
-/* Format codes
- * F_LJUST '-'
- * F_SIGN '+'
- * F_BLANK ' '
- * F_ALT '#'
- * F_ZERO '0'
- */
-#define F_LJUST (1<<0)
-#define F_SIGN (1<<1)
-#define F_BLANK (1<<2)
-#define F_ALT (1<<3)
-#define F_ZERO (1<<4)
-
-Py_LOCAL_INLINE(int)
-formatfloat(char *buf, size_t buflen, int flags,
- int prec, int type, PyObject *v)
-{
- /* fmt = '%#.' + `prec` + `type`
- worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/
- char fmt[20];
- double x;
- x = PyFloat_AsDouble(v);
- if (x == -1.0 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "float argument required");
- return -1;
- }
- if (prec < 0)
- prec = 6;
- if (type == 'f' && fabs(x)/1e25 >= 1e25)
- type = 'g';
- /* Worst case length calc to ensure no buffer overrun:
-
- 'g' formats:
- fmt = %#.<prec>g
- buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
- for any double rep.)
- len = 1 + prec + 1 + 2 + 5 = 9 + prec
-
- 'f' formats:
- buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50)
- len = 1 + 50 + 1 + prec = 52 + prec
-
- If prec=0 the effective precision is 1 (the leading digit is
- always given), therefore increase the length by one.
-
- */
- if ((type == 'g' && buflen <= (size_t)10 + (size_t)prec) ||
- (type == 'f' && buflen <= (size_t)53 + (size_t)prec)) {
- PyErr_SetString(PyExc_OverflowError,
- "formatted float is too long (precision too large?)");
- return -1;
- }
- PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c",
- (flags&F_ALT) ? "#" : "",
- prec, type);
- PyOS_ascii_formatd(buf, buflen, fmt, x);
- return (int)strlen(buf);
-}
-
-/* _PyString_FormatLong emulates the format codes d, u, o, x and X, and
- * the F_ALT flag, for Python's long (unbounded) ints. It's not used for
- * Python's regular ints.
- * Return value: a new PyString*, or NULL if error.
- * . *pbuf is set to point into it,
- * *plen set to the # of chars following that.
- * Caller must decref it when done using pbuf.
- * The string starting at *pbuf is of the form
- * "-"? ("0x" | "0X")? digit+
- * "0x"/"0X" are present only for x and X conversions, with F_ALT
- * set in flags. The case of hex digits will be correct,
- * There will be at least prec digits, zero-filled on the left if
- * necessary to get that many.
- * val object to be converted
- * flags bitmask of format flags; only F_ALT is looked at
- * prec minimum number of digits; 0-fill on left if needed
- * type a character in [duoxX]; u acts the same as d
- *
- * CAUTION: o, x and X conversions on regular ints can never
- * produce a '-' sign, but can for Python's unbounded ints.
- */
-PyObject*
-_PyString_FormatLong(PyObject *val, int flags, int prec, int type,
- char **pbuf, int *plen)
-{
- PyObject *result = NULL;
- char *buf;
- Py_ssize_t i;
- int sign; /* 1 if '-', else 0 */
- int len; /* number of characters */
- Py_ssize_t llen;
- int numdigits; /* len == numnondigits + numdigits */
- int numnondigits = 0;
-
- switch (type) {
- case 'd':
- case 'u':
- result = val->ob_type->tp_str(val);
- break;
- case 'o':
- result = val->ob_type->tp_as_number->nb_oct(val);
- break;
- case 'x':
- case 'X':
- numnondigits = 2;
- result = val->ob_type->tp_as_number->nb_hex(val);
- break;
- default:
- assert(!"'type' not in [duoxX]");
- }
- if (!result)
- return NULL;
-
- buf = PyString_AsString(result);
- if (!buf) {
- Py_DECREF(result);
- return NULL;
- }
-
- /* To modify the string in-place, there can only be one reference. */
- if (result->ob_refcnt != 1) {
- PyErr_BadInternalCall();
- return NULL;
- }
- llen = PyString_Size(result);
- if (llen > INT_MAX) {
- PyErr_SetString(PyExc_ValueError, "string too large in _PyString_FormatLong");
- return NULL;
- }
- len = (int)llen;
- if (buf[len-1] == 'L') {
- --len;
- buf[len] = '\0';
- }
- sign = buf[0] == '-';
- numnondigits += sign;
- numdigits = len - numnondigits;
- assert(numdigits > 0);
-
- /* Get rid of base marker unless F_ALT */
- if ((flags & F_ALT) == 0) {
- /* Need to skip 0x, 0X or 0. */
- int skipped = 0;
- switch (type) {
- case 'o':
- assert(buf[sign] == '0');
- /* If 0 is only digit, leave it alone. */
- if (numdigits > 1) {
- skipped = 1;
- --numdigits;
- }
- break;
- case 'x':
- case 'X':
- assert(buf[sign] == '0');
- assert(buf[sign + 1] == 'x');
- skipped = 2;
- numnondigits -= 2;
- break;
- }
- if (skipped) {
- buf += skipped;
- len -= skipped;
- if (sign)
- buf[0] = '-';
- }
- assert(len == numnondigits + numdigits);
- assert(numdigits > 0);
- }
-
- /* Fill with leading zeroes to meet minimum width. */
- if (prec > numdigits) {
- PyObject *r1 = PyString_FromStringAndSize(NULL,
- numnondigits + prec);
- char *b1;
- if (!r1) {
- Py_DECREF(result);
- return NULL;
- }
- b1 = PyString_AS_STRING(r1);
- for (i = 0; i < numnondigits; ++i)
- *b1++ = *buf++;
- for (i = 0; i < prec - numdigits; i++)
- *b1++ = '0';
- for (i = 0; i < numdigits; i++)
- *b1++ = *buf++;
- *b1 = '\0';
- Py_DECREF(result);
- result = r1;
- buf = PyString_AS_STRING(result);
- len = numnondigits + prec;
- }
-
- /* Fix up case for hex conversions. */
- if (type == 'X') {
- /* Need to convert all lower case letters to upper case.
- and need to convert 0x to 0X (and -0x to -0X). */
- for (i = 0; i < len; i++)
- if (buf[i] >= 'a' && buf[i] <= 'x')
- buf[i] -= 'a'-'A';
- }
- *pbuf = buf;
- *plen = len;
- return result;
-}
-
-Py_LOCAL_INLINE(int)
-formatint(char *buf, size_t buflen, int flags,
- int prec, int type, PyObject *v)
-{
- /* fmt = '%#.' + `prec` + 'l' + `type`
- worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
- + 1 + 1 = 24 */
- char fmt[64]; /* plenty big enough! */
- char *sign;
- long x;
-
- x = PyInt_AsLong(v);
- if (x == -1 && PyErr_Occurred()) {
- PyErr_SetString(PyExc_TypeError, "int argument required");
- return -1;
- }
- if (x < 0 && type == 'u') {
- type = 'd';
- }
- if (x < 0 && (type == 'x' || type == 'X' || type == 'o'))
- sign = "-";
- else
- sign = "";
- if (prec < 0)
- prec = 1;
-
- if ((flags & F_ALT) &&
- (type == 'x' || type == 'X')) {
- /* When converting under %#x or %#X, there are a number
- * of issues that cause pain:
- * - when 0 is being converted, the C standard leaves off
- * the '0x' or '0X', which is inconsistent with other
- * %#x/%#X conversions and inconsistent with Python's
- * hex() function
- * - there are platforms that violate the standard and
- * convert 0 with the '0x' or '0X'
- * (Metrowerks, Compaq Tru64)
- * - there are platforms that give '0x' when converting
- * under %#X, but convert 0 in accordance with the
- * standard (OS/2 EMX)
- *
- * We can achieve the desired consistency by inserting our
- * own '0x' or '0X' prefix, and substituting %x/%X in place
- * of %#x/%#X.
- *
- * Note that this is the same approach as used in
- * formatint() in unicodeobject.c
- */
- PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c",
- sign, type, prec, type);
- }
- else {
- PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c",
- sign, (flags&F_ALT) ? "#" : "",
- prec, type);
- }
-
- /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal))
- * worst case buf = '-0x' + [0-9]*prec, where prec >= 11
- */
- if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) {
- PyErr_SetString(PyExc_OverflowError,
- "formatted integer is too long (precision too large?)");
- return -1;
- }
- if (sign[0])
- PyOS_snprintf(buf, buflen, fmt, -x);
- else
- PyOS_snprintf(buf, buflen, fmt, x);
- return (int)strlen(buf);
-}
-
-Py_LOCAL_INLINE(int)
-formatchar(char *buf, size_t buflen, PyObject *v)
-{
- /* presume that the buffer is at least 2 characters long */
- if (PyString_Check(v)) {
- if (!PyArg_Parse(v, "c;%c requires int or char", &buf[0]))
- return -1;
- }
- else {
- if (!PyArg_Parse(v, "b;%c requires int or char", &buf[0]))
- return -1;
- }
- buf[1] = '\0';
- return 1;
-}
-
-/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)
-
- FORMATBUFLEN is the length of the buffer in which the floats, ints, &
- chars are formatted. XXX This is a magic number. Each formatting
- routine does bounds checking to ensure no overflow, but a better
- solution may be to malloc a buffer of appropriate size for each
- format. For now, the current solution is sufficient.
-*/
-#define FORMATBUFLEN (size_t)120
-
-PyObject *
-PyString_Format(PyObject *format, PyObject *args)
-{
- char *fmt, *res;
- Py_ssize_t arglen, argidx;
- Py_ssize_t reslen, rescnt, fmtcnt;
- int args_owned = 0;
- PyObject *result, *orig_args;
-#ifdef Py_USING_UNICODE
- PyObject *v, *w;
-#endif
- PyObject *dict = NULL;
- if (format == NULL || !PyString_Check(format) || args == NULL) {
- PyErr_BadInternalCall();
- return NULL;
- }
- orig_args = args;
- fmt = PyString_AS_STRING(format);
- fmtcnt = PyString_GET_SIZE(format);
- reslen = rescnt = fmtcnt + 100;
- result = PyString_FromStringAndSize((char *)NULL, reslen);
- if (result == NULL)
- return NULL;
- res = PyString_AsString(result);
- if (PyTuple_Check(args)) {
- arglen = PyTuple_GET_SIZE(args);
- argidx = 0;
- }
- else {
- arglen = -1;
- argidx = -2;
- }
- if (args->ob_type->tp_as_mapping && !PyTuple_Check(args) &&
- !PyObject_TypeCheck(args, &PyBaseString_Type))
- dict = args;
- while (--fmtcnt >= 0) {
- if (*fmt != '%') {
- if (--rescnt < 0) {
- rescnt = fmtcnt + 100;
- reslen += rescnt;
- if (_PyString_Resize(&result, reslen) < 0)
- return NULL;
- res = PyString_AS_STRING(result)
- + reslen - rescnt;
- --rescnt;
- }
- *res++ = *fmt++;
- }
- else {
- /* Got a format specifier */
- int flags = 0;
- Py_ssize_t width = -1;
- int prec = -1;
- int c = '\0';
- int fill;
- PyObject *v = NULL;
- PyObject *temp = NULL;
- char *pbuf;
- int sign;
- Py_ssize_t len;
- char formatbuf[FORMATBUFLEN];
- /* For format{float,int,char}() */
-#ifdef Py_USING_UNICODE
- char *fmt_start = fmt;
- Py_ssize_t argidx_start = argidx;
-#endif
-
- fmt++;
- if (*fmt == '(') {
- char *keystart;
- Py_ssize_t keylen;
- PyObject *key;
- int pcount = 1;
-
- if (dict == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "format requires a mapping");
- goto error;
- }
- ++fmt;
- --fmtcnt;
- keystart = fmt;
- /* Skip over balanced parentheses */
- while (pcount > 0 && --fmtcnt >= 0) {
- if (*fmt == ')')
- --pcount;
- else if (*fmt == '(')
- ++pcount;
- fmt++;
- }
- keylen = fmt - keystart - 1;
- if (fmtcnt < 0 || pcount > 0) {
- PyErr_SetString(PyExc_ValueError,
- "incomplete format key");
- goto error;
- }
- key = PyString_FromStringAndSize(keystart,
- keylen);
- if (key == NULL)
- goto error;
- if (args_owned) {
- Py_DECREF(args);
- args_owned = 0;
- }
- args = PyObject_GetItem(dict, key);
- Py_DECREF(key);
- if (args == NULL) {
- goto error;
- }
- args_owned = 1;
- arglen = -1;
- argidx = -2;
- }
- while (--fmtcnt >= 0) {
- switch (c = *fmt++) {
- case '-': flags |= F_LJUST; continue;
- case '+': flags |= F_SIGN; continue;
- case ' ': flags |= F_BLANK; continue;
- case '#': flags |= F_ALT; continue;
- case '0': flags |= F_ZERO; continue;
- }
- break;
- }
- if (c == '*') {
- v = getnextarg(args, arglen, &argidx);
- if (v == NULL)
- goto error;
- if (!PyInt_Check(v)) {
- PyErr_SetString(PyExc_TypeError,
- "* wants int");
- goto error;
- }
- width = PyInt_AsLong(v);
- if (width < 0) {
- flags |= F_LJUST;
- width = -width;
- }
- if (--fmtcnt >= 0)
- c = *fmt++;
- }
- else if (c >= 0 && isdigit(c)) {
- width = c - '0';
- while (--fmtcnt >= 0) {
- c = Py_CHARMASK(*fmt++);
- if (!isdigit(c))
- break;
- if ((width*10) / 10 != width) {
- PyErr_SetString(
- PyExc_ValueError,
- "width too big");
- goto error;
- }
- width = width*10 + (c - '0');
- }
- }
- if (c == '.') {
- prec = 0;
- if (--fmtcnt >= 0)
- c = *fmt++;
- if (c == '*') {
- v = getnextarg(args, arglen, &argidx);
- if (v == NULL)
- goto error;
- if (!PyInt_Check(v)) {
- PyErr_SetString(
- PyExc_TypeError,
- "* wants int");
- goto error;
- }
- prec = PyInt_AsLong(v);
- if (prec < 0)
- prec = 0;
- if (--fmtcnt >= 0)
- c = *fmt++;
- }
- else if (c >= 0 && isdigit(c)) {
- prec = c - '0';
- while (--fmtcnt >= 0) {
- c = Py_CHARMASK(*fmt++);
- if (!isdigit(c))
- break;
- if ((prec*10) / 10 != prec) {
- PyErr_SetString(
- PyExc_ValueError,
- "prec too big");
- goto error;
- }
- prec = prec*10 + (c - '0');
- }
- }
- } /* prec */
- if (fmtcnt >= 0) {
- if (c == 'h' || c == 'l' || c == 'L') {
- if (--fmtcnt >= 0)
- c = *fmt++;
- }
- }
- if (fmtcnt < 0) {
- PyErr_SetString(PyExc_ValueError,
- "incomplete format");
- goto error;
- }
- if (c != '%') {
- v = getnextarg(args, arglen, &argidx);
- if (v == NULL)
- goto error;
- }
- sign = 0;
- fill = ' ';
- switch (c) {
- case '%':
- pbuf = "%";
- len = 1;
- break;
- case 's':
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(v)) {
- fmt = fmt_start;
- argidx = argidx_start;
- goto unicode;
- }
-#endif
- temp = _PyObject_Str(v);
-#ifdef Py_USING_UNICODE
- if (temp != NULL && PyUnicode_Check(temp)) {
- Py_DECREF(temp);
- fmt = fmt_start;
- argidx = argidx_start;
- goto unicode;
- }
-#endif
- /* Fall through */
- case 'r':
- if (c == 'r')
- temp = PyObject_Repr(v);
- if (temp == NULL)
- goto error;
- if (!PyString_Check(temp)) {
- PyErr_SetString(PyExc_TypeError,
- "%s argument has non-string str()");
- Py_DECREF(temp);
- goto error;
- }
- pbuf = PyString_AS_STRING(temp);
- len = PyString_GET_SIZE(temp);
- if (prec >= 0 && len > prec)
- len = prec;
- break;
- case 'i':
- case 'd':
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- if (c == 'i')
- c = 'd';
- if (PyLong_Check(v)) {
- int ilen;
- temp = _PyString_FormatLong(v, flags,
- prec, c, &pbuf, &ilen);
- len = ilen;
- if (!temp)
- goto error;
- sign = 1;
- }
- else {
- pbuf = formatbuf;
- len = formatint(pbuf,
- sizeof(formatbuf),
- flags, prec, c, v);
- if (len < 0)
- goto error;
- sign = 1;
- }
- if (flags & F_ZERO)
- fill = '0';
- break;
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- if (c == 'F')
- c = 'f';
- pbuf = formatbuf;
- len = formatfloat(pbuf, sizeof(formatbuf),
- flags, prec, c, v);
- if (len < 0)
- goto error;
- sign = 1;
- if (flags & F_ZERO)
- fill = '0';
- break;
- case 'c':
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(v)) {
- fmt = fmt_start;
- argidx = argidx_start;
- goto unicode;
- }
-#endif
- pbuf = formatbuf;
- len = formatchar(pbuf, sizeof(formatbuf), v);
- if (len < 0)
- goto error;
- break;
- default:
- PyErr_Format(PyExc_ValueError,
- "unsupported format character '%c' (0x%x) "
- "at index %zd",
- c, c,
- (Py_ssize_t)(fmt - 1 -
- PyString_AsString(format)));
- goto error;
- }
- if (sign) {
- if (*pbuf == '-' || *pbuf == '+') {
- sign = *pbuf++;
- len--;
- }
- else if (flags & F_SIGN)
- sign = '+';
- else if (flags & F_BLANK)
- sign = ' ';
- else
- sign = 0;
- }
- if (width < len)
- width = len;
- if (rescnt - (sign != 0) < width) {
- reslen -= rescnt;
- rescnt = width + fmtcnt + 100;
- reslen += rescnt;
- if (reslen < 0) {
- Py_DECREF(result);
- Py_XDECREF(temp);
- return PyErr_NoMemory();
- }
- if (_PyString_Resize(&result, reslen) < 0) {
- Py_XDECREF(temp);
- return NULL;
- }
- res = PyString_AS_STRING(result)
- + reslen - rescnt;
- }
- if (sign) {
- if (fill != ' ')
- *res++ = sign;
- rescnt--;
- if (width > len)
- width--;
- }
- if ((flags & F_ALT) && (c == 'x' || c == 'X')) {
- assert(pbuf[0] == '0');
- assert(pbuf[1] == c);
- if (fill != ' ') {
- *res++ = *pbuf++;
- *res++ = *pbuf++;
- }
- rescnt -= 2;
- width -= 2;
- if (width < 0)
- width = 0;
- len -= 2;
- }
- if (width > len && !(flags & F_LJUST)) {
- do {
- --rescnt;
- *res++ = fill;
- } while (--width > len);
- }
- if (fill == ' ') {
- if (sign)
- *res++ = sign;
- if ((flags & F_ALT) &&
- (c == 'x' || c == 'X')) {
- assert(pbuf[0] == '0');
- assert(pbuf[1] == c);
- *res++ = *pbuf++;
- *res++ = *pbuf++;
- }
- }
- Py_MEMCPY(res, pbuf, len);
- res += len;
- rescnt -= len;
- while (--width >= len) {
- --rescnt;
- *res++ = ' ';
- }
- if (dict && (argidx < arglen) && c != '%') {
- PyErr_SetString(PyExc_TypeError,
- "not all arguments converted during string formatting");
- Py_XDECREF(temp);
- goto error;
- }
- Py_XDECREF(temp);
- } /* '%' */
- } /* until end */
- if (argidx < arglen && !dict) {
- PyErr_SetString(PyExc_TypeError,
- "not all arguments converted during string formatting");
- goto error;
- }
- if (args_owned) {
- Py_DECREF(args);
- }
- _PyString_Resize(&result, reslen - rescnt);
- return result;
-
-#ifdef Py_USING_UNICODE
- unicode:
- if (args_owned) {
- Py_DECREF(args);
- args_owned = 0;
- }
- /* Fiddle args right (remove the first argidx arguments) */
- if (PyTuple_Check(orig_args) && argidx > 0) {
- PyObject *v;
- Py_ssize_t n = PyTuple_GET_SIZE(orig_args) - argidx;
- v = PyTuple_New(n);
- if (v == NULL)
- goto error;
- while (--n >= 0) {
- PyObject *w = PyTuple_GET_ITEM(orig_args, n + argidx);
- Py_INCREF(w);
- PyTuple_SET_ITEM(v, n, w);
- }
- args = v;
- } else {
- Py_INCREF(orig_args);
- args = orig_args;
- }
- args_owned = 1;
- /* Take what we have of the result and let the Unicode formatting
- function format the rest of the input. */
- rescnt = res - PyString_AS_STRING(result);
- if (_PyString_Resize(&result, rescnt))
- goto error;
- fmtcnt = PyString_GET_SIZE(format) - \
- (fmt - PyString_AS_STRING(format));
- format = PyUnicode_Decode(fmt, fmtcnt, NULL, NULL);
- if (format == NULL)
- goto error;
- v = PyUnicode_Format(format, args);
- Py_DECREF(format);
- if (v == NULL)
- goto error;
- /* Paste what we have (result) to what the Unicode formatting
- function returned (v) and return the result (or error) */
- w = PyUnicode_Concat(result, v);
- Py_DECREF(result);
- Py_DECREF(v);
- Py_DECREF(args);
- return w;
-#endif /* Py_USING_UNICODE */
-
- error:
- Py_DECREF(result);
- if (args_owned) {
- Py_DECREF(args);
- }
- return NULL;
-}
-
-void
-PyString_InternInPlace(PyObject **p)
-{
- register PyStringObject *s = (PyStringObject *)(*p);
- PyObject *t;
- if (s == NULL || !PyString_Check(s))
- Py_FatalError("PyString_InternInPlace: strings only please!");
- /* If it's a string subclass, we don't really know what putting
- it in the interned dict might do. */
- if (!PyString_CheckExact(s))
- return;
- if (PyString_CHECK_INTERNED(s))
- return;
- if (interned == NULL) {
- interned = PyDict_New();
- if (interned == NULL) {
- PyErr_Clear(); /* Don't leave an exception */
- return;
- }
- }
- t = PyDict_GetItem(interned, (PyObject *)s);
- if (t) {
- Py_INCREF(t);
- Py_DECREF(*p);
- *p = t;
- return;
- }
-
- if (PyDict_SetItem(interned, (PyObject *)s, (PyObject *)s) < 0) {
- PyErr_Clear();
- return;
- }
- /* The two references in interned are not counted by refcnt.
- The string deallocator will take care of this */
- s->ob_refcnt -= 2;
- PyString_CHECK_INTERNED(s) = SSTATE_INTERNED_MORTAL;
-}
-
-void
-PyString_InternImmortal(PyObject **p)
-{
- PyString_InternInPlace(p);
- if (PyString_CHECK_INTERNED(*p) != SSTATE_INTERNED_IMMORTAL) {
- PyString_CHECK_INTERNED(*p) = SSTATE_INTERNED_IMMORTAL;
- Py_INCREF(*p);
- }
-}
-
-
-PyObject *
-PyString_InternFromString(const char *cp)
-{
- PyObject *s = PyString_FromString(cp);
- if (s == NULL)
- return NULL;
- PyString_InternInPlace(&s);
- return s;
-}
-
-void
-PyString_Fini(void)
-{
- int i;
- for (i = 0; i < UCHAR_MAX + 1; i++) {
- Py_XDECREF(characters[i]);
- characters[i] = NULL;
- }
- Py_XDECREF(nullstring);
- nullstring = NULL;
-}
-
-void _Py_ReleaseInternedStrings(void)
-{
- PyObject *keys;
- PyStringObject *s;
- Py_ssize_t i, n;
-
- if (interned == NULL || !PyDict_Check(interned))
- return;
- keys = PyDict_Keys(interned);
- if (keys == NULL || !PyList_Check(keys)) {
- PyErr_Clear();
- return;
- }
-
- /* Since _Py_ReleaseInternedStrings() is intended to help a leak
- detector, interned strings are not forcibly deallocated; rather, we
- give them their stolen references back, and then clear and DECREF
- the interned dict. */
-
- fprintf(stderr, "releasing interned strings\n");
- n = PyList_GET_SIZE(keys);
- for (i = 0; i < n; i++) {
- s = (PyStringObject *) PyList_GET_ITEM(keys, i);
- switch (s->ob_sstate) {
- case SSTATE_NOT_INTERNED:
- /* XXX Shouldn't happen */
- break;
- case SSTATE_INTERNED_IMMORTAL:
- s->ob_refcnt += 1;
- break;
- case SSTATE_INTERNED_MORTAL:
- s->ob_refcnt += 2;
- break;
- default:
- Py_FatalError("Inconsistent interned string state.");
- }
- s->ob_sstate = SSTATE_NOT_INTERNED;
- }
- Py_DECREF(keys);
- PyDict_Clear(interned);
- Py_DECREF(interned);
- interned = NULL;
-}
diff --git a/sys/src/cmd/python/Objects/structseq.c b/sys/src/cmd/python/Objects/structseq.c
deleted file mode 100644
index 7ac2a1f61..000000000
--- a/sys/src/cmd/python/Objects/structseq.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/* Implementation helper: a struct that looks like a tuple. See timemodule
- and posixmodule for example uses. */
-
-#include "Python.h"
-#include "structmember.h"
-#include "structseq.h"
-
-static char visible_length_key[] = "n_sequence_fields";
-static char real_length_key[] = "n_fields";
-static char unnamed_fields_key[] = "n_unnamed_fields";
-
-/* Fields with this name have only a field index, not a field name.
- They are only allowed for indices < n_visible_fields. */
-char *PyStructSequence_UnnamedField = "unnamed field";
-
-#define VISIBLE_SIZE(op) ((op)->ob_size)
-#define VISIBLE_SIZE_TP(tp) PyInt_AsLong( \
- PyDict_GetItemString((tp)->tp_dict, visible_length_key))
-
-#define REAL_SIZE_TP(tp) PyInt_AsLong( \
- PyDict_GetItemString((tp)->tp_dict, real_length_key))
-#define REAL_SIZE(op) REAL_SIZE_TP((op)->ob_type)
-
-#define UNNAMED_FIELDS_TP(tp) PyInt_AsLong( \
- PyDict_GetItemString((tp)->tp_dict, unnamed_fields_key))
-#define UNNAMED_FIELDS(op) UNNAMED_FIELDS_TP((op)->ob_type)
-
-
-PyObject *
-PyStructSequence_New(PyTypeObject *type)
-{
- PyStructSequence *obj;
-
- obj = PyObject_New(PyStructSequence, type);
- obj->ob_size = VISIBLE_SIZE_TP(type);
-
- return (PyObject*) obj;
-}
-
-static void
-structseq_dealloc(PyStructSequence *obj)
-{
- Py_ssize_t i, size;
-
- size = REAL_SIZE(obj);
- for (i = 0; i < size; ++i) {
- Py_XDECREF(obj->ob_item[i]);
- }
- PyObject_Del(obj);
-}
-
-static Py_ssize_t
-structseq_length(PyStructSequence *obj)
-{
- return VISIBLE_SIZE(obj);
-}
-
-static PyObject*
-structseq_item(PyStructSequence *obj, Py_ssize_t i)
-{
- if (i < 0 || i >= VISIBLE_SIZE(obj)) {
- PyErr_SetString(PyExc_IndexError, "tuple index out of range");
- return NULL;
- }
- Py_INCREF(obj->ob_item[i]);
- return obj->ob_item[i];
-}
-
-static PyObject*
-structseq_slice(PyStructSequence *obj, Py_ssize_t low, Py_ssize_t high)
-{
- PyTupleObject *np;
- Py_ssize_t i;
-
- if (low < 0)
- low = 0;
- if (high > VISIBLE_SIZE(obj))
- high = VISIBLE_SIZE(obj);
- if (high < low)
- high = low;
- np = (PyTupleObject *)PyTuple_New(high-low);
- if (np == NULL)
- return NULL;
- for(i = low; i < high; ++i) {
- PyObject *v = obj->ob_item[i];
- Py_INCREF(v);
- PyTuple_SET_ITEM(np, i-low, v);
- }
- return (PyObject *) np;
-}
-
-static PyObject *
-structseq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *arg = NULL;
- PyObject *dict = NULL;
- PyObject *ob;
- PyStructSequence *res = NULL;
- Py_ssize_t len, min_len, max_len, i, n_unnamed_fields;
- static char *kwlist[] = {"sequence", "dict", 0};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:structseq",
- kwlist, &arg, &dict))
- return NULL;
-
- arg = PySequence_Fast(arg, "constructor requires a sequence");
-
- if (!arg) {
- return NULL;
- }
-
- if (dict && !PyDict_Check(dict)) {
- PyErr_Format(PyExc_TypeError,
- "%.500s() takes a dict as second arg, if any",
- type->tp_name);
- Py_DECREF(arg);
- return NULL;
- }
-
- len = PySequence_Fast_GET_SIZE(arg);
- min_len = VISIBLE_SIZE_TP(type);
- max_len = REAL_SIZE_TP(type);
- n_unnamed_fields = UNNAMED_FIELDS_TP(type);
-
- if (min_len != max_len) {
- if (len < min_len) {
- PyErr_Format(PyExc_TypeError,
- "%.500s() takes an at least %zd-sequence (%zd-sequence given)",
- type->tp_name, min_len, len);
- Py_DECREF(arg);
- return NULL;
- }
-
- if (len > max_len) {
- PyErr_Format(PyExc_TypeError,
- "%.500s() takes an at most %zd-sequence (%zd-sequence given)",
- type->tp_name, max_len, len);
- Py_DECREF(arg);
- return NULL;
- }
- }
- else {
- if (len != min_len) {
- PyErr_Format(PyExc_TypeError,
- "%.500s() takes a %zd-sequence (%zd-sequence given)",
- type->tp_name, min_len, len);
- Py_DECREF(arg);
- return NULL;
- }
- }
-
- res = (PyStructSequence*) PyStructSequence_New(type);
- if (res == NULL) {
- return NULL;
- }
- for (i = 0; i < len; ++i) {
- PyObject *v = PySequence_Fast_GET_ITEM(arg, i);
- Py_INCREF(v);
- res->ob_item[i] = v;
- }
- for (; i < max_len; ++i) {
- if (dict && (ob = PyDict_GetItemString(
- dict, type->tp_members[i-n_unnamed_fields].name))) {
- }
- else {
- ob = Py_None;
- }
- Py_INCREF(ob);
- res->ob_item[i] = ob;
- }
-
- Py_DECREF(arg);
- return (PyObject*) res;
-}
-
-static PyObject *
-make_tuple(PyStructSequence *obj)
-{
- return structseq_slice(obj, 0, VISIBLE_SIZE(obj));
-}
-
-static PyObject *
-structseq_repr(PyStructSequence *obj)
-{
- PyObject *tup, *str;
- tup = make_tuple(obj);
- str = PyObject_Repr(tup);
- Py_DECREF(tup);
- return str;
-}
-
-static PyObject *
-structseq_concat(PyStructSequence *obj, PyObject *b)
-{
- PyObject *tup, *result;
- tup = make_tuple(obj);
- result = PySequence_Concat(tup, b);
- Py_DECREF(tup);
- return result;
-}
-
-static PyObject *
-structseq_repeat(PyStructSequence *obj, Py_ssize_t n)
-{
- PyObject *tup, *result;
- tup = make_tuple(obj);
- result = PySequence_Repeat(tup, n);
- Py_DECREF(tup);
- return result;
-}
-
-static int
-structseq_contains(PyStructSequence *obj, PyObject *o)
-{
- PyObject *tup;
- int result;
- tup = make_tuple(obj);
- if (!tup)
- return -1;
- result = PySequence_Contains(tup, o);
- Py_DECREF(tup);
- return result;
-}
-
-static long
-structseq_hash(PyObject *obj)
-{
- PyObject *tup;
- long result;
- tup = make_tuple((PyStructSequence*) obj);
- if (!tup)
- return -1;
- result = PyObject_Hash(tup);
- Py_DECREF(tup);
- return result;
-}
-
-static PyObject *
-structseq_richcompare(PyObject *obj, PyObject *o2, int op)
-{
- PyObject *tup, *result;
- tup = make_tuple((PyStructSequence*) obj);
- result = PyObject_RichCompare(tup, o2, op);
- Py_DECREF(tup);
- return result;
-}
-
-static PyObject *
-structseq_reduce(PyStructSequence* self)
-{
- PyObject* tup;
- PyObject* dict;
- PyObject* result;
- Py_ssize_t n_fields, n_visible_fields, n_unnamed_fields;
- int i;
-
- n_fields = REAL_SIZE(self);
- n_visible_fields = VISIBLE_SIZE(self);
- n_unnamed_fields = UNNAMED_FIELDS(self);
- tup = PyTuple_New(n_visible_fields);
- if (!tup) {
- return NULL;
- }
-
- dict = PyDict_New();
- if (!dict) {
- Py_DECREF(tup);
- return NULL;
- }
-
- for (i = 0; i < n_visible_fields; i++) {
- Py_INCREF(self->ob_item[i]);
- PyTuple_SET_ITEM(tup, i, self->ob_item[i]);
- }
-
- for (; i < n_fields; i++) {
- char *n = self->ob_type->tp_members[i-n_unnamed_fields].name;
- PyDict_SetItemString(dict, n,
- self->ob_item[i]);
- }
-
- result = Py_BuildValue("(O(OO))", self->ob_type, tup, dict);
-
- Py_DECREF(tup);
- Py_DECREF(dict);
-
- return result;
-}
-
-static PySequenceMethods structseq_as_sequence = {
- (lenfunc)structseq_length,
- (binaryfunc)structseq_concat, /* sq_concat */
- (ssizeargfunc)structseq_repeat, /* sq_repeat */
- (ssizeargfunc)structseq_item, /* sq_item */
- (ssizessizeargfunc)structseq_slice, /* sq_slice */
- 0, /* sq_ass_item */
- 0, /* sq_ass_slice */
- (objobjproc)structseq_contains, /* sq_contains */
-};
-
-static PyMethodDef structseq_methods[] = {
- {"__reduce__", (PyCFunction)structseq_reduce,
- METH_NOARGS, NULL},
- {NULL, NULL}
-};
-
-static PyTypeObject _struct_sequence_template = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- NULL, /* tp_name */
- 0, /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)structseq_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)structseq_repr, /* tp_repr */
- 0, /* tp_as_number */
- &structseq_as_sequence, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- structseq_hash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT, /* tp_flags */
- NULL, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- structseq_richcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- structseq_methods, /* tp_methods */
- NULL, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- structseq_new, /* tp_new */
-};
-
-void
-PyStructSequence_InitType(PyTypeObject *type, PyStructSequence_Desc *desc)
-{
- PyObject *dict;
- PyMemberDef* members;
- int n_members, n_unnamed_members, i, k;
-
-#ifdef Py_TRACE_REFS
- /* if the type object was chained, unchain it first
- before overwriting its storage */
- if (type->_ob_next) {
- _Py_ForgetReference((PyObject*)type);
- }
-#endif
-
- n_unnamed_members = 0;
- for (i = 0; desc->fields[i].name != NULL; ++i)
- if (desc->fields[i].name == PyStructSequence_UnnamedField)
- n_unnamed_members++;
- n_members = i;
-
- memcpy(type, &_struct_sequence_template, sizeof(PyTypeObject));
- type->tp_name = desc->name;
- type->tp_doc = desc->doc;
- type->tp_basicsize = sizeof(PyStructSequence)+
- sizeof(PyObject*)*(n_members-1);
- type->tp_itemsize = 0;
-
- members = PyMem_NEW(PyMemberDef, n_members-n_unnamed_members+1);
- if (members == NULL)
- return;
-
- for (i = k = 0; i < n_members; ++i) {
- if (desc->fields[i].name == PyStructSequence_UnnamedField)
- continue;
- members[k].name = desc->fields[i].name;
- members[k].type = T_OBJECT;
- members[k].offset = offsetof(PyStructSequence, ob_item)
- + i * sizeof(PyObject*);
- members[k].flags = READONLY;
- members[k].doc = desc->fields[i].doc;
- k++;
- }
- members[k].name = NULL;
-
- type->tp_members = members;
-
- if (PyType_Ready(type) < 0)
- return;
- Py_INCREF(type);
-
- dict = type->tp_dict;
- PyDict_SetItemString(dict, visible_length_key,
- PyInt_FromLong((long) desc->n_in_sequence));
- PyDict_SetItemString(dict, real_length_key,
- PyInt_FromLong((long) n_members));
- PyDict_SetItemString(dict, unnamed_fields_key,
- PyInt_FromLong((long) n_unnamed_members));
-}
diff --git a/sys/src/cmd/python/Objects/tupleobject.c b/sys/src/cmd/python/Objects/tupleobject.c
deleted file mode 100644
index 6f3711f1f..000000000
--- a/sys/src/cmd/python/Objects/tupleobject.c
+++ /dev/null
@@ -1,890 +0,0 @@
-
-/* Tuple object implementation */
-
-#include "Python.h"
-
-/* Speed optimization to avoid frequent malloc/free of small tuples */
-#ifndef MAXSAVESIZE
-#define MAXSAVESIZE 20 /* Largest tuple to save on free list */
-#endif
-#ifndef MAXSAVEDTUPLES
-#define MAXSAVEDTUPLES 2000 /* Maximum number of tuples of each size to save */
-#endif
-
-#if MAXSAVESIZE > 0
-/* Entries 1 up to MAXSAVESIZE are free lists, entry 0 is the empty
- tuple () of which at most one instance will be allocated.
-*/
-static PyTupleObject *free_tuples[MAXSAVESIZE];
-static int num_free_tuples[MAXSAVESIZE];
-#endif
-#ifdef COUNT_ALLOCS
-int fast_tuple_allocs;
-int tuple_zero_allocs;
-#endif
-
-PyObject *
-PyTuple_New(register Py_ssize_t size)
-{
- register PyTupleObject *op;
- Py_ssize_t i;
- if (size < 0) {
- PyErr_BadInternalCall();
- return NULL;
- }
-#if MAXSAVESIZE > 0
- if (size == 0 && free_tuples[0]) {
- op = free_tuples[0];
- Py_INCREF(op);
-#ifdef COUNT_ALLOCS
- tuple_zero_allocs++;
-#endif
- return (PyObject *) op;
- }
- if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {
- free_tuples[size] = (PyTupleObject *) op->ob_item[0];
- num_free_tuples[size]--;
-#ifdef COUNT_ALLOCS
- fast_tuple_allocs++;
-#endif
- /* Inline PyObject_InitVar */
-#ifdef Py_TRACE_REFS
- op->ob_size = size;
- op->ob_type = &PyTuple_Type;
-#endif
- _Py_NewReference((PyObject *)op);
- }
- else
-#endif
- {
- Py_ssize_t nbytes = size * sizeof(PyObject *);
- /* Check for overflow */
- if (nbytes / sizeof(PyObject *) != (size_t)size ||
- (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *))
- <= 0)
- {
- return PyErr_NoMemory();
- }
- op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
- if (op == NULL)
- return NULL;
- }
- for (i=0; i < size; i++)
- op->ob_item[i] = NULL;
-#if MAXSAVESIZE > 0
- if (size == 0) {
- free_tuples[0] = op;
- ++num_free_tuples[0];
- Py_INCREF(op); /* extra INCREF so that this is never freed */
- }
-#endif
- _PyObject_GC_TRACK(op);
- return (PyObject *) op;
-}
-
-Py_ssize_t
-PyTuple_Size(register PyObject *op)
-{
- if (!PyTuple_Check(op)) {
- PyErr_BadInternalCall();
- return -1;
- }
- else
- return ((PyTupleObject *)op)->ob_size;
-}
-
-PyObject *
-PyTuple_GetItem(register PyObject *op, register Py_ssize_t i)
-{
- if (!PyTuple_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {
- PyErr_SetString(PyExc_IndexError, "tuple index out of range");
- return NULL;
- }
- return ((PyTupleObject *)op) -> ob_item[i];
-}
-
-int
-PyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem)
-{
- register PyObject *olditem;
- register PyObject **p;
- if (!PyTuple_Check(op) || op->ob_refcnt != 1) {
- Py_XDECREF(newitem);
- PyErr_BadInternalCall();
- return -1;
- }
- if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {
- Py_XDECREF(newitem);
- PyErr_SetString(PyExc_IndexError,
- "tuple assignment index out of range");
- return -1;
- }
- p = ((PyTupleObject *)op) -> ob_item + i;
- olditem = *p;
- *p = newitem;
- Py_XDECREF(olditem);
- return 0;
-}
-
-PyObject *
-PyTuple_Pack(Py_ssize_t n, ...)
-{
- Py_ssize_t i;
- PyObject *o;
- PyObject *result;
- PyObject **items;
- va_list vargs;
-
- va_start(vargs, n);
- result = PyTuple_New(n);
- if (result == NULL)
- return NULL;
- items = ((PyTupleObject *)result)->ob_item;
- for (i = 0; i < n; i++) {
- o = va_arg(vargs, PyObject *);
- Py_INCREF(o);
- items[i] = o;
- }
- va_end(vargs);
- return result;
-}
-
-
-/* Methods */
-
-static void
-tupledealloc(register PyTupleObject *op)
-{
- register Py_ssize_t i;
- register Py_ssize_t len = op->ob_size;
- PyObject_GC_UnTrack(op);
- Py_TRASHCAN_SAFE_BEGIN(op)
- if (len > 0) {
- i = len;
- while (--i >= 0)
- Py_XDECREF(op->ob_item[i]);
-#if MAXSAVESIZE > 0
- if (len < MAXSAVESIZE &&
- num_free_tuples[len] < MAXSAVEDTUPLES &&
- op->ob_type == &PyTuple_Type)
- {
- op->ob_item[0] = (PyObject *) free_tuples[len];
- num_free_tuples[len]++;
- free_tuples[len] = op;
- goto done; /* return */
- }
-#endif
- }
- op->ob_type->tp_free((PyObject *)op);
-done:
- Py_TRASHCAN_SAFE_END(op)
-}
-
-static int
-tupleprint(PyTupleObject *op, FILE *fp, int flags)
-{
- Py_ssize_t i;
- fprintf(fp, "(");
- for (i = 0; i < op->ob_size; i++) {
- if (i > 0)
- fprintf(fp, ", ");
- if (PyObject_Print(op->ob_item[i], fp, 0) != 0)
- return -1;
- }
- if (op->ob_size == 1)
- fprintf(fp, ",");
- fprintf(fp, ")");
- return 0;
-}
-
-static PyObject *
-tuplerepr(PyTupleObject *v)
-{
- Py_ssize_t i, n;
- PyObject *s, *temp;
- PyObject *pieces, *result = NULL;
-
- n = v->ob_size;
- if (n == 0)
- return PyString_FromString("()");
-
- pieces = PyTuple_New(n);
- if (pieces == NULL)
- return NULL;
-
- /* Do repr() on each element. */
- for (i = 0; i < n; ++i) {
- s = PyObject_Repr(v->ob_item[i]);
- if (s == NULL)
- goto Done;
- PyTuple_SET_ITEM(pieces, i, s);
- }
-
- /* Add "()" decorations to the first and last items. */
- assert(n > 0);
- s = PyString_FromString("(");
- if (s == NULL)
- goto Done;
- temp = PyTuple_GET_ITEM(pieces, 0);
- PyString_ConcatAndDel(&s, temp);
- PyTuple_SET_ITEM(pieces, 0, s);
- if (s == NULL)
- goto Done;
-
- s = PyString_FromString(n == 1 ? ",)" : ")");
- if (s == NULL)
- goto Done;
- temp = PyTuple_GET_ITEM(pieces, n-1);
- PyString_ConcatAndDel(&temp, s);
- PyTuple_SET_ITEM(pieces, n-1, temp);
- if (temp == NULL)
- goto Done;
-
- /* Paste them all together with ", " between. */
- s = PyString_FromString(", ");
- if (s == NULL)
- goto Done;
- result = _PyString_Join(s, pieces);
- Py_DECREF(s);
-
-Done:
- Py_DECREF(pieces);
- return result;
-}
-
-/* The addend 82520, was selected from the range(0, 1000000) for
- generating the greatest number of prime multipliers for tuples
- upto length eight:
-
- 1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533,
- 1330111, 1412633, 1165069, 1247599, 1495177, 1577699
-*/
-
-static long
-tuplehash(PyTupleObject *v)
-{
- register long x, y;
- register Py_ssize_t len = v->ob_size;
- register PyObject **p;
- long mult = 1000003L;
- x = 0x345678L;
- p = v->ob_item;
- while (--len >= 0) {
- y = PyObject_Hash(*p++);
- if (y == -1)
- return -1;
- x = (x ^ y) * mult;
- /* the cast might truncate len; that doesn't change hash stability */
- mult += (long)(82520L + len + len);
- }
- x += 97531L;
- if (x == -1)
- x = -2;
- return x;
-}
-
-static Py_ssize_t
-tuplelength(PyTupleObject *a)
-{
- return a->ob_size;
-}
-
-static int
-tuplecontains(PyTupleObject *a, PyObject *el)
-{
- Py_ssize_t i;
- int cmp;
-
- for (i = 0, cmp = 0 ; cmp == 0 && i < a->ob_size; ++i)
- cmp = PyObject_RichCompareBool(el, PyTuple_GET_ITEM(a, i),
- Py_EQ);
- return cmp;
-}
-
-static PyObject *
-tupleitem(register PyTupleObject *a, register Py_ssize_t i)
-{
- if (i < 0 || i >= a->ob_size) {
- PyErr_SetString(PyExc_IndexError, "tuple index out of range");
- return NULL;
- }
- Py_INCREF(a->ob_item[i]);
- return a->ob_item[i];
-}
-
-static PyObject *
-tupleslice(register PyTupleObject *a, register Py_ssize_t ilow,
- register Py_ssize_t ihigh)
-{
- register PyTupleObject *np;
- PyObject **src, **dest;
- register Py_ssize_t i;
- Py_ssize_t len;
- if (ilow < 0)
- ilow = 0;
- if (ihigh > a->ob_size)
- ihigh = a->ob_size;
- if (ihigh < ilow)
- ihigh = ilow;
- if (ilow == 0 && ihigh == a->ob_size && PyTuple_CheckExact(a)) {
- Py_INCREF(a);
- return (PyObject *)a;
- }
- len = ihigh - ilow;
- np = (PyTupleObject *)PyTuple_New(len);
- if (np == NULL)
- return NULL;
- src = a->ob_item + ilow;
- dest = np->ob_item;
- for (i = 0; i < len; i++) {
- PyObject *v = src[i];
- Py_INCREF(v);
- dest[i] = v;
- }
- return (PyObject *)np;
-}
-
-PyObject *
-PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j)
-{
- if (op == NULL || !PyTuple_Check(op)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return tupleslice((PyTupleObject *)op, i, j);
-}
-
-static PyObject *
-tupleconcat(register PyTupleObject *a, register PyObject *bb)
-{
- register Py_ssize_t size;
- register Py_ssize_t i;
- PyObject **src, **dest;
- PyTupleObject *np;
- if (!PyTuple_Check(bb)) {
- PyErr_Format(PyExc_TypeError,
- "can only concatenate tuple (not \"%.200s\") to tuple",
- bb->ob_type->tp_name);
- return NULL;
- }
-#define b ((PyTupleObject *)bb)
- size = a->ob_size + b->ob_size;
- if (size < 0)
- return PyErr_NoMemory();
- np = (PyTupleObject *) PyTuple_New(size);
- if (np == NULL) {
- return NULL;
- }
- src = a->ob_item;
- dest = np->ob_item;
- for (i = 0; i < a->ob_size; i++) {
- PyObject *v = src[i];
- Py_INCREF(v);
- dest[i] = v;
- }
- src = b->ob_item;
- dest = np->ob_item + a->ob_size;
- for (i = 0; i < b->ob_size; i++) {
- PyObject *v = src[i];
- Py_INCREF(v);
- dest[i] = v;
- }
- return (PyObject *)np;
-#undef b
-}
-
-static PyObject *
-tuplerepeat(PyTupleObject *a, Py_ssize_t n)
-{
- Py_ssize_t i, j;
- Py_ssize_t size;
- PyTupleObject *np;
- PyObject **p, **items;
- if (n < 0)
- n = 0;
- if (a->ob_size == 0 || n == 1) {
- if (PyTuple_CheckExact(a)) {
- /* Since tuples are immutable, we can return a shared
- copy in this case */
- Py_INCREF(a);
- return (PyObject *)a;
- }
- if (a->ob_size == 0)
- return PyTuple_New(0);
- }
- size = a->ob_size * n;
- if (size/a->ob_size != n)
- return PyErr_NoMemory();
- np = (PyTupleObject *) PyTuple_New(size);
- if (np == NULL)
- return NULL;
- p = np->ob_item;
- items = a->ob_item;
- for (i = 0; i < n; i++) {
- for (j = 0; j < a->ob_size; j++) {
- *p = items[j];
- Py_INCREF(*p);
- p++;
- }
- }
- return (PyObject *) np;
-}
-
-static int
-tupletraverse(PyTupleObject *o, visitproc visit, void *arg)
-{
- Py_ssize_t i;
-
- for (i = o->ob_size; --i >= 0; )
- Py_VISIT(o->ob_item[i]);
- return 0;
-}
-
-static PyObject *
-tuplerichcompare(PyObject *v, PyObject *w, int op)
-{
- PyTupleObject *vt, *wt;
- Py_ssize_t i;
- Py_ssize_t vlen, wlen;
-
- if (!PyTuple_Check(v) || !PyTuple_Check(w)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
-
- vt = (PyTupleObject *)v;
- wt = (PyTupleObject *)w;
-
- vlen = vt->ob_size;
- wlen = wt->ob_size;
-
- /* Note: the corresponding code for lists has an "early out" test
- * here when op is EQ or NE and the lengths differ. That pays there,
- * but Tim was unable to find any real code where EQ/NE tuple
- * compares don't have the same length, so testing for it here would
- * have cost without benefit.
- */
-
- /* Search for the first index where items are different.
- * Note that because tuples are immutable, it's safe to reuse
- * vlen and wlen across the comparison calls.
- */
- for (i = 0; i < vlen && i < wlen; i++) {
- int k = PyObject_RichCompareBool(vt->ob_item[i],
- wt->ob_item[i], Py_EQ);
- if (k < 0)
- return NULL;
- if (!k)
- break;
- }
-
- if (i >= vlen || i >= wlen) {
- /* No more items to compare -- compare sizes */
- int cmp;
- PyObject *res;
- switch (op) {
- case Py_LT: cmp = vlen < wlen; break;
- case Py_LE: cmp = vlen <= wlen; break;
- case Py_EQ: cmp = vlen == wlen; break;
- case Py_NE: cmp = vlen != wlen; break;
- case Py_GT: cmp = vlen > wlen; break;
- case Py_GE: cmp = vlen >= wlen; break;
- default: return NULL; /* cannot happen */
- }
- if (cmp)
- res = Py_True;
- else
- res = Py_False;
- Py_INCREF(res);
- return res;
- }
-
- /* We have an item that differs -- shortcuts for EQ/NE */
- if (op == Py_EQ) {
- Py_INCREF(Py_False);
- return Py_False;
- }
- if (op == Py_NE) {
- Py_INCREF(Py_True);
- return Py_True;
- }
-
- /* Compare the final item again using the proper operator */
- return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);
-}
-
-static PyObject *
-tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyObject *
-tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *arg = NULL;
- static char *kwlist[] = {"sequence", 0};
-
- if (type != &PyTuple_Type)
- return tuple_subtype_new(type, args, kwds);
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:tuple", kwlist, &arg))
- return NULL;
-
- if (arg == NULL)
- return PyTuple_New(0);
- else
- return PySequence_Tuple(arg);
-}
-
-static PyObject *
-tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *tmp, *newobj, *item;
- Py_ssize_t i, n;
-
- assert(PyType_IsSubtype(type, &PyTuple_Type));
- tmp = tuple_new(&PyTuple_Type, args, kwds);
- if (tmp == NULL)
- return NULL;
- assert(PyTuple_Check(tmp));
- newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
- if (newobj == NULL)
- return NULL;
- for (i = 0; i < n; i++) {
- item = PyTuple_GET_ITEM(tmp, i);
- Py_INCREF(item);
- PyTuple_SET_ITEM(newobj, i, item);
- }
- Py_DECREF(tmp);
- return newobj;
-}
-
-PyDoc_STRVAR(tuple_doc,
-"tuple() -> an empty tuple\n"
-"tuple(sequence) -> tuple initialized from sequence's items\n"
-"\n"
-"If the argument is a tuple, the return value is the same object.");
-
-static PySequenceMethods tuple_as_sequence = {
- (lenfunc)tuplelength, /* sq_length */
- (binaryfunc)tupleconcat, /* sq_concat */
- (ssizeargfunc)tuplerepeat, /* sq_repeat */
- (ssizeargfunc)tupleitem, /* sq_item */
- (ssizessizeargfunc)tupleslice, /* sq_slice */
- 0, /* sq_ass_item */
- 0, /* sq_ass_slice */
- (objobjproc)tuplecontains, /* sq_contains */
-};
-
-static PyObject*
-tuplesubscript(PyTupleObject* self, PyObject* item)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += PyTuple_GET_SIZE(self);
- return tupleitem(self, i);
- }
- else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength, cur, i;
- PyObject* result;
- PyObject* it;
- PyObject **src, **dest;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item,
- PyTuple_GET_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
- return NULL;
- }
-
- if (slicelength <= 0) {
- return PyTuple_New(0);
- }
- else {
- result = PyTuple_New(slicelength);
- if (!result) return NULL;
-
- src = self->ob_item;
- dest = ((PyTupleObject *)result)->ob_item;
- for (cur = start, i = 0; i < slicelength;
- cur += step, i++) {
- it = src[cur];
- Py_INCREF(it);
- dest[i] = it;
- }
-
- return result;
- }
- }
- else {
- PyErr_SetString(PyExc_TypeError,
- "tuple indices must be integers");
- return NULL;
- }
-}
-
-static PyObject *
-tuple_getnewargs(PyTupleObject *v)
-{
- return Py_BuildValue("(N)", tupleslice(v, 0, v->ob_size));
-
-}
-
-static PyMethodDef tuple_methods[] = {
- {"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},
- {NULL, NULL} /* sentinel */
-};
-
-static PyMappingMethods tuple_as_mapping = {
- (lenfunc)tuplelength,
- (binaryfunc)tuplesubscript,
- 0
-};
-
-static PyObject *tuple_iter(PyObject *seq);
-
-PyTypeObject PyTuple_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "tuple",
- sizeof(PyTupleObject) - sizeof(PyObject *),
- sizeof(PyObject *),
- (destructor)tupledealloc, /* tp_dealloc */
- (printfunc)tupleprint, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- (reprfunc)tuplerepr, /* tp_repr */
- 0, /* tp_as_number */
- &tuple_as_sequence, /* tp_as_sequence */
- &tuple_as_mapping, /* tp_as_mapping */
- (hashfunc)tuplehash, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- tuple_doc, /* tp_doc */
- (traverseproc)tupletraverse, /* tp_traverse */
- 0, /* tp_clear */
- tuplerichcompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- tuple_iter, /* tp_iter */
- 0, /* tp_iternext */
- tuple_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- tuple_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
-
-/* The following function breaks the notion that tuples are immutable:
- it changes the size of a tuple. We get away with this only if there
- is only one module referencing the object. You can also think of it
- as creating a new tuple object and destroying the old one, only more
- efficiently. In any case, don't use this if the tuple may already be
- known to some other part of the code. */
-
-int
-_PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
-{
- register PyTupleObject *v;
- register PyTupleObject *sv;
- Py_ssize_t i;
- Py_ssize_t oldsize;
-
- v = (PyTupleObject *) *pv;
- if (v == NULL || v->ob_type != &PyTuple_Type ||
- (v->ob_size != 0 && v->ob_refcnt != 1)) {
- *pv = 0;
- Py_XDECREF(v);
- PyErr_BadInternalCall();
- return -1;
- }
- oldsize = v->ob_size;
- if (oldsize == newsize)
- return 0;
-
- if (oldsize == 0) {
- /* Empty tuples are often shared, so we should never
- resize them in-place even if we do own the only
- (current) reference */
- Py_DECREF(v);
- *pv = PyTuple_New(newsize);
- return *pv == NULL ? -1 : 0;
- }
-
- /* XXX UNREF/NEWREF interface should be more symmetrical */
- _Py_DEC_REFTOTAL;
- _PyObject_GC_UNTRACK(v);
- _Py_ForgetReference((PyObject *) v);
- /* DECREF items deleted by shrinkage */
- for (i = newsize; i < oldsize; i++) {
- Py_XDECREF(v->ob_item[i]);
- v->ob_item[i] = NULL;
- }
- sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
- if (sv == NULL) {
- *pv = NULL;
- PyObject_GC_Del(v);
- return -1;
- }
- _Py_NewReference((PyObject *) sv);
- /* Zero out items added by growing */
- if (newsize > oldsize)
- memset(&sv->ob_item[oldsize], 0,
- sizeof(*sv->ob_item) * (newsize - oldsize));
- *pv = (PyObject *) sv;
- _PyObject_GC_TRACK(sv);
- return 0;
-}
-
-void
-PyTuple_Fini(void)
-{
-#if MAXSAVESIZE > 0
- int i;
-
- Py_XDECREF(free_tuples[0]);
- free_tuples[0] = NULL;
-
- for (i = 1; i < MAXSAVESIZE; i++) {
- PyTupleObject *p, *q;
- p = free_tuples[i];
- free_tuples[i] = NULL;
- while (p) {
- q = p;
- p = (PyTupleObject *)(p->ob_item[0]);
- PyObject_GC_Del(q);
- }
- }
-#endif
-}
-
-/*********************** Tuple Iterator **************************/
-
-typedef struct {
- PyObject_HEAD
- long it_index;
- PyTupleObject *it_seq; /* Set to NULL when iterator is exhausted */
-} tupleiterobject;
-
-static void
-tupleiter_dealloc(tupleiterobject *it)
-{
- _PyObject_GC_UNTRACK(it);
- Py_XDECREF(it->it_seq);
- PyObject_GC_Del(it);
-}
-
-static int
-tupleiter_traverse(tupleiterobject *it, visitproc visit, void *arg)
-{
- Py_VISIT(it->it_seq);
- return 0;
-}
-
-static PyObject *
-tupleiter_next(tupleiterobject *it)
-{
- PyTupleObject *seq;
- PyObject *item;
-
- assert(it != NULL);
- seq = it->it_seq;
- if (seq == NULL)
- return NULL;
- assert(PyTuple_Check(seq));
-
- if (it->it_index < PyTuple_GET_SIZE(seq)) {
- item = PyTuple_GET_ITEM(seq, it->it_index);
- ++it->it_index;
- Py_INCREF(item);
- return item;
- }
-
- Py_DECREF(seq);
- it->it_seq = NULL;
- return NULL;
-}
-
-static PyObject *
-tupleiter_len(tupleiterobject *it)
-{
- Py_ssize_t len = 0;
- if (it->it_seq)
- len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;
- return PyInt_FromSsize_t(len);
-}
-
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
-
-static PyMethodDef tupleiter_methods[] = {
- {"__length_hint__", (PyCFunction)tupleiter_len, METH_NOARGS, length_hint_doc},
- {NULL, NULL} /* sentinel */
-};
-
-PyTypeObject PyTupleIter_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "tupleiterator", /* tp_name */
- sizeof(tupleiterobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- (destructor)tupleiter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
- 0, /* tp_doc */
- (traverseproc)tupleiter_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)tupleiter_next, /* tp_iternext */
- tupleiter_methods, /* tp_methods */
- 0,
-};
-
-static PyObject *
-tuple_iter(PyObject *seq)
-{
- tupleiterobject *it;
-
- if (!PyTuple_Check(seq)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- it = PyObject_GC_New(tupleiterobject, &PyTupleIter_Type);
- if (it == NULL)
- return NULL;
- it->it_index = 0;
- Py_INCREF(seq);
- it->it_seq = (PyTupleObject *)seq;
- _PyObject_GC_TRACK(it);
- return (PyObject *)it;
-}
diff --git a/sys/src/cmd/python/Objects/typeobject.c b/sys/src/cmd/python/Objects/typeobject.c
deleted file mode 100644
index 8a6f78266..000000000
--- a/sys/src/cmd/python/Objects/typeobject.c
+++ /dev/null
@@ -1,5891 +0,0 @@
-/* Type object implementation */
-
-#include "Python.h"
-#include "structmember.h"
-
-#include <ctype.h>
-
-static PyMemberDef type_members[] = {
- {"__basicsize__", T_INT, offsetof(PyTypeObject,tp_basicsize),READONLY},
- {"__itemsize__", T_INT, offsetof(PyTypeObject, tp_itemsize), READONLY},
- {"__flags__", T_LONG, offsetof(PyTypeObject, tp_flags), READONLY},
- {"__weakrefoffset__", T_LONG,
- offsetof(PyTypeObject, tp_weaklistoffset), READONLY},
- {"__base__", T_OBJECT, offsetof(PyTypeObject, tp_base), READONLY},
- {"__dictoffset__", T_LONG,
- offsetof(PyTypeObject, tp_dictoffset), READONLY},
- {"__mro__", T_OBJECT, offsetof(PyTypeObject, tp_mro), READONLY},
- {0}
-};
-
-static PyObject *
-type_name(PyTypeObject *type, void *context)
-{
- const char *s;
-
- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
- PyHeapTypeObject* et = (PyHeapTypeObject*)type;
-
- Py_INCREF(et->ht_name);
- return et->ht_name;
- }
- else {
- s = strrchr(type->tp_name, '.');
- if (s == NULL)
- s = type->tp_name;
- else
- s++;
- return PyString_FromString(s);
- }
-}
-
-static int
-type_set_name(PyTypeObject *type, PyObject *value, void *context)
-{
- PyHeapTypeObject* et;
-
- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
- PyErr_Format(PyExc_TypeError,
- "can't set %s.__name__", type->tp_name);
- return -1;
- }
- if (!value) {
- PyErr_Format(PyExc_TypeError,
- "can't delete %s.__name__", type->tp_name);
- return -1;
- }
- if (!PyString_Check(value)) {
- PyErr_Format(PyExc_TypeError,
- "can only assign string to %s.__name__, not '%s'",
- type->tp_name, value->ob_type->tp_name);
- return -1;
- }
- if (strlen(PyString_AS_STRING(value))
- != (size_t)PyString_GET_SIZE(value)) {
- PyErr_Format(PyExc_ValueError,
- "__name__ must not contain null bytes");
- return -1;
- }
-
- et = (PyHeapTypeObject*)type;
-
- Py_INCREF(value);
-
- Py_DECREF(et->ht_name);
- et->ht_name = value;
-
- type->tp_name = PyString_AS_STRING(value);
-
- return 0;
-}
-
-static PyObject *
-type_module(PyTypeObject *type, void *context)
-{
- PyObject *mod;
- char *s;
-
- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) {
- mod = PyDict_GetItemString(type->tp_dict, "__module__");
- if (!mod) {
- PyErr_Format(PyExc_AttributeError, "__module__");
- return 0;
- }
- Py_XINCREF(mod);
- return mod;
- }
- else {
- s = strrchr(type->tp_name, '.');
- if (s != NULL)
- return PyString_FromStringAndSize(
- type->tp_name, (Py_ssize_t)(s - type->tp_name));
- return PyString_FromString("__builtin__");
- }
-}
-
-static int
-type_set_module(PyTypeObject *type, PyObject *value, void *context)
-{
- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
- PyErr_Format(PyExc_TypeError,
- "can't set %s.__module__", type->tp_name);
- return -1;
- }
- if (!value) {
- PyErr_Format(PyExc_TypeError,
- "can't delete %s.__module__", type->tp_name);
- return -1;
- }
-
- return PyDict_SetItemString(type->tp_dict, "__module__", value);
-}
-
-static PyObject *
-type_get_bases(PyTypeObject *type, void *context)
-{
- Py_INCREF(type->tp_bases);
- return type->tp_bases;
-}
-
-static PyTypeObject *best_base(PyObject *);
-static int mro_internal(PyTypeObject *);
-static int compatible_for_assignment(PyTypeObject *, PyTypeObject *, char *);
-static int add_subclass(PyTypeObject*, PyTypeObject*);
-static void remove_subclass(PyTypeObject *, PyTypeObject *);
-static void update_all_slots(PyTypeObject *);
-
-typedef int (*update_callback)(PyTypeObject *, void *);
-static int update_subclasses(PyTypeObject *type, PyObject *name,
- update_callback callback, void *data);
-static int recurse_down_subclasses(PyTypeObject *type, PyObject *name,
- update_callback callback, void *data);
-
-static int
-mro_subclasses(PyTypeObject *type, PyObject* temp)
-{
- PyTypeObject *subclass;
- PyObject *ref, *subclasses, *old_mro;
- Py_ssize_t i, n;
-
- subclasses = type->tp_subclasses;
- if (subclasses == NULL)
- return 0;
- assert(PyList_Check(subclasses));
- n = PyList_GET_SIZE(subclasses);
- for (i = 0; i < n; i++) {
- ref = PyList_GET_ITEM(subclasses, i);
- assert(PyWeakref_CheckRef(ref));
- subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);
- assert(subclass != NULL);
- if ((PyObject *)subclass == Py_None)
- continue;
- assert(PyType_Check(subclass));
- old_mro = subclass->tp_mro;
- if (mro_internal(subclass) < 0) {
- subclass->tp_mro = old_mro;
- return -1;
- }
- else {
- PyObject* tuple;
- tuple = PyTuple_Pack(2, subclass, old_mro);
- Py_DECREF(old_mro);
- if (!tuple)
- return -1;
- if (PyList_Append(temp, tuple) < 0)
- return -1;
- Py_DECREF(tuple);
- }
- if (mro_subclasses(subclass, temp) < 0)
- return -1;
- }
- return 0;
-}
-
-static int
-type_set_bases(PyTypeObject *type, PyObject *value, void *context)
-{
- Py_ssize_t i;
- int r = 0;
- PyObject *ob, *temp;
- PyTypeObject *new_base, *old_base;
- PyObject *old_bases, *old_mro;
-
- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
- PyErr_Format(PyExc_TypeError,
- "can't set %s.__bases__", type->tp_name);
- return -1;
- }
- if (!value) {
- PyErr_Format(PyExc_TypeError,
- "can't delete %s.__bases__", type->tp_name);
- return -1;
- }
- if (!PyTuple_Check(value)) {
- PyErr_Format(PyExc_TypeError,
- "can only assign tuple to %s.__bases__, not %s",
- type->tp_name, value->ob_type->tp_name);
- return -1;
- }
- if (PyTuple_GET_SIZE(value) == 0) {
- PyErr_Format(PyExc_TypeError,
- "can only assign non-empty tuple to %s.__bases__, not ()",
- type->tp_name);
- return -1;
- }
- for (i = 0; i < PyTuple_GET_SIZE(value); i++) {
- ob = PyTuple_GET_ITEM(value, i);
- if (!PyClass_Check(ob) && !PyType_Check(ob)) {
- PyErr_Format(
- PyExc_TypeError,
- "%s.__bases__ must be tuple of old- or new-style classes, not '%s'",
- type->tp_name, ob->ob_type->tp_name);
- return -1;
- }
- if (PyType_Check(ob)) {
- if (PyType_IsSubtype((PyTypeObject*)ob, type)) {
- PyErr_SetString(PyExc_TypeError,
- "a __bases__ item causes an inheritance cycle");
- return -1;
- }
- }
- }
-
- new_base = best_base(value);
-
- if (!new_base) {
- return -1;
- }
-
- if (!compatible_for_assignment(type->tp_base, new_base, "__bases__"))
- return -1;
-
- Py_INCREF(new_base);
- Py_INCREF(value);
-
- old_bases = type->tp_bases;
- old_base = type->tp_base;
- old_mro = type->tp_mro;
-
- type->tp_bases = value;
- type->tp_base = new_base;
-
- if (mro_internal(type) < 0) {
- goto bail;
- }
-
- temp = PyList_New(0);
- if (!temp)
- goto bail;
-
- r = mro_subclasses(type, temp);
-
- if (r < 0) {
- for (i = 0; i < PyList_Size(temp); i++) {
- PyTypeObject* cls;
- PyObject* mro;
- PyArg_UnpackTuple(PyList_GET_ITEM(temp, i),
- "", 2, 2, &cls, &mro);
- Py_DECREF(cls->tp_mro);
- cls->tp_mro = mro;
- Py_INCREF(cls->tp_mro);
- }
- Py_DECREF(temp);
- goto bail;
- }
-
- Py_DECREF(temp);
-
- /* any base that was in __bases__ but now isn't, we
- need to remove |type| from its tp_subclasses.
- conversely, any class now in __bases__ that wasn't
- needs to have |type| added to its subclasses. */
-
- /* for now, sod that: just remove from all old_bases,
- add to all new_bases */
-
- for (i = PyTuple_GET_SIZE(old_bases) - 1; i >= 0; i--) {
- ob = PyTuple_GET_ITEM(old_bases, i);
- if (PyType_Check(ob)) {
- remove_subclass(
- (PyTypeObject*)ob, type);
- }
- }
-
- for (i = PyTuple_GET_SIZE(value) - 1; i >= 0; i--) {
- ob = PyTuple_GET_ITEM(value, i);
- if (PyType_Check(ob)) {
- if (add_subclass((PyTypeObject*)ob, type) < 0)
- r = -1;
- }
- }
-
- update_all_slots(type);
-
- Py_DECREF(old_bases);
- Py_DECREF(old_base);
- Py_DECREF(old_mro);
-
- return r;
-
- bail:
- Py_DECREF(type->tp_bases);
- Py_DECREF(type->tp_base);
- if (type->tp_mro != old_mro) {
- Py_DECREF(type->tp_mro);
- }
-
- type->tp_bases = old_bases;
- type->tp_base = old_base;
- type->tp_mro = old_mro;
-
- return -1;
-}
-
-static PyObject *
-type_dict(PyTypeObject *type, void *context)
-{
- if (type->tp_dict == NULL) {
- Py_INCREF(Py_None);
- return Py_None;
- }
- return PyDictProxy_New(type->tp_dict);
-}
-
-static PyObject *
-type_get_doc(PyTypeObject *type, void *context)
-{
- PyObject *result;
- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE) && type->tp_doc != NULL)
- return PyString_FromString(type->tp_doc);
- result = PyDict_GetItemString(type->tp_dict, "__doc__");
- if (result == NULL) {
- result = Py_None;
- Py_INCREF(result);
- }
- else if (result->ob_type->tp_descr_get) {
- result = result->ob_type->tp_descr_get(result, NULL,
- (PyObject *)type);
- }
- else {
- Py_INCREF(result);
- }
- return result;
-}
-
-static PyGetSetDef type_getsets[] = {
- {"__name__", (getter)type_name, (setter)type_set_name, NULL},
- {"__bases__", (getter)type_get_bases, (setter)type_set_bases, NULL},
- {"__module__", (getter)type_module, (setter)type_set_module, NULL},
- {"__dict__", (getter)type_dict, NULL, NULL},
- {"__doc__", (getter)type_get_doc, NULL, NULL},
- {0}
-};
-
-static int
-type_compare(PyObject *v, PyObject *w)
-{
- /* This is called with type objects only. So we
- can just compare the addresses. */
- Py_uintptr_t vv = (Py_uintptr_t)v;
- Py_uintptr_t ww = (Py_uintptr_t)w;
- return (vv < ww) ? -1 : (vv > ww) ? 1 : 0;
-}
-
-static PyObject *
-type_repr(PyTypeObject *type)
-{
- PyObject *mod, *name, *rtn;
- char *kind;
-
- mod = type_module(type, NULL);
- if (mod == NULL)
- PyErr_Clear();
- else if (!PyString_Check(mod)) {
- Py_DECREF(mod);
- mod = NULL;
- }
- name = type_name(type, NULL);
- if (name == NULL)
- return NULL;
-
- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
- kind = "class";
- else
- kind = "type";
-
- if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__")) {
- rtn = PyString_FromFormat("<%s '%s.%s'>",
- kind,
- PyString_AS_STRING(mod),
- PyString_AS_STRING(name));
- }
- else
- rtn = PyString_FromFormat("<%s '%s'>", kind, type->tp_name);
-
- Py_XDECREF(mod);
- Py_DECREF(name);
- return rtn;
-}
-
-static PyObject *
-type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *obj;
-
- if (type->tp_new == NULL) {
- PyErr_Format(PyExc_TypeError,
- "cannot create '%.100s' instances",
- type->tp_name);
- return NULL;
- }
-
- obj = type->tp_new(type, args, kwds);
- if (obj != NULL) {
- /* Ugly exception: when the call was type(something),
- don't call tp_init on the result. */
- if (type == &PyType_Type &&
- PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
- (kwds == NULL ||
- (PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
- return obj;
- /* If the returned object is not an instance of type,
- it won't be initialized. */
- if (!PyType_IsSubtype(obj->ob_type, type))
- return obj;
- type = obj->ob_type;
- if (PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS) &&
- type->tp_init != NULL &&
- type->tp_init(obj, args, kwds) < 0) {
- Py_DECREF(obj);
- obj = NULL;
- }
- }
- return obj;
-}
-
-PyObject *
-PyType_GenericAlloc(PyTypeObject *type, Py_ssize_t nitems)
-{
- PyObject *obj;
- const size_t size = _PyObject_VAR_SIZE(type, nitems+1);
- /* note that we need to add one, for the sentinel */
-
- if (PyType_IS_GC(type))
- obj = _PyObject_GC_Malloc(size);
- else
- obj = (PyObject *)PyObject_MALLOC(size);
-
- if (obj == NULL)
- return PyErr_NoMemory();
-
- memset(obj, '\0', size);
-
- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
- Py_INCREF(type);
-
- if (type->tp_itemsize == 0)
- PyObject_INIT(obj, type);
- else
- (void) PyObject_INIT_VAR((PyVarObject *)obj, type, nitems);
-
- if (PyType_IS_GC(type))
- _PyObject_GC_TRACK(obj);
- return obj;
-}
-
-PyObject *
-PyType_GenericNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- return type->tp_alloc(type, 0);
-}
-
-/* Helpers for subtyping */
-
-static int
-traverse_slots(PyTypeObject *type, PyObject *self, visitproc visit, void *arg)
-{
- Py_ssize_t i, n;
- PyMemberDef *mp;
-
- n = type->ob_size;
- mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);
- for (i = 0; i < n; i++, mp++) {
- if (mp->type == T_OBJECT_EX) {
- char *addr = (char *)self + mp->offset;
- PyObject *obj = *(PyObject **)addr;
- if (obj != NULL) {
- int err = visit(obj, arg);
- if (err)
- return err;
- }
- }
- }
- return 0;
-}
-
-static int
-subtype_traverse(PyObject *self, visitproc visit, void *arg)
-{
- PyTypeObject *type, *base;
- traverseproc basetraverse;
-
- /* Find the nearest base with a different tp_traverse,
- and traverse slots while we're at it */
- type = self->ob_type;
- base = type;
- while ((basetraverse = base->tp_traverse) == subtype_traverse) {
- if (base->ob_size) {
- int err = traverse_slots(base, self, visit, arg);
- if (err)
- return err;
- }
- base = base->tp_base;
- assert(base);
- }
-
- if (type->tp_dictoffset != base->tp_dictoffset) {
- PyObject **dictptr = _PyObject_GetDictPtr(self);
- if (dictptr && *dictptr)
- Py_VISIT(*dictptr);
- }
-
- if (type->tp_flags & Py_TPFLAGS_HEAPTYPE)
- /* For a heaptype, the instances count as references
- to the type. Traverse the type so the collector
- can find cycles involving this link. */
- Py_VISIT(type);
-
- if (basetraverse)
- return basetraverse(self, visit, arg);
- return 0;
-}
-
-static void
-clear_slots(PyTypeObject *type, PyObject *self)
-{
- Py_ssize_t i, n;
- PyMemberDef *mp;
-
- n = type->ob_size;
- mp = PyHeapType_GET_MEMBERS((PyHeapTypeObject *)type);
- for (i = 0; i < n; i++, mp++) {
- if (mp->type == T_OBJECT_EX && !(mp->flags & READONLY)) {
- char *addr = (char *)self + mp->offset;
- PyObject *obj = *(PyObject **)addr;
- if (obj != NULL) {
- *(PyObject **)addr = NULL;
- Py_DECREF(obj);
- }
- }
- }
-}
-
-static int
-subtype_clear(PyObject *self)
-{
- PyTypeObject *type, *base;
- inquiry baseclear;
-
- /* Find the nearest base with a different tp_clear
- and clear slots while we're at it */
- type = self->ob_type;
- base = type;
- while ((baseclear = base->tp_clear) == subtype_clear) {
- if (base->ob_size)
- clear_slots(base, self);
- base = base->tp_base;
- assert(base);
- }
-
- /* There's no need to clear the instance dict (if any);
- the collector will call its tp_clear handler. */
-
- if (baseclear)
- return baseclear(self);
- return 0;
-}
-
-static void
-subtype_dealloc(PyObject *self)
-{
- PyTypeObject *type, *base;
- destructor basedealloc;
-
- /* Extract the type; we expect it to be a heap type */
- type = self->ob_type;
- assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
-
- /* Test whether the type has GC exactly once */
-
- if (!PyType_IS_GC(type)) {
- /* It's really rare to find a dynamic type that doesn't have
- GC; it can only happen when deriving from 'object' and not
- adding any slots or instance variables. This allows
- certain simplifications: there's no need to call
- clear_slots(), or DECREF the dict, or clear weakrefs. */
-
- /* Maybe call finalizer; exit early if resurrected */
- if (type->tp_del) {
- type->tp_del(self);
- if (self->ob_refcnt > 0)
- return;
- }
-
- /* Find the nearest base with a different tp_dealloc */
- base = type;
- while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
- assert(base->ob_size == 0);
- base = base->tp_base;
- assert(base);
- }
-
- /* Call the base tp_dealloc() */
- assert(basedealloc);
- basedealloc(self);
-
- /* Can't reference self beyond this point */
- Py_DECREF(type);
-
- /* Done */
- return;
- }
-
- /* We get here only if the type has GC */
-
- /* UnTrack and re-Track around the trashcan macro, alas */
- /* See explanation at end of function for full disclosure */
- PyObject_GC_UnTrack(self);
- ++_PyTrash_delete_nesting;
- Py_TRASHCAN_SAFE_BEGIN(self);
- --_PyTrash_delete_nesting;
- /* DO NOT restore GC tracking at this point. weakref callbacks
- * (if any, and whether directly here or indirectly in something we
- * call) may trigger GC, and if self is tracked at that point, it
- * will look like trash to GC and GC will try to delete self again.
- */
-
- /* Find the nearest base with a different tp_dealloc */
- base = type;
- while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
- base = base->tp_base;
- assert(base);
- }
-
- /* If we added a weaklist, we clear it. Do this *before* calling
- the finalizer (__del__), clearing slots, or clearing the instance
- dict. */
-
- if (type->tp_weaklistoffset && !base->tp_weaklistoffset)
- PyObject_ClearWeakRefs(self);
-
- /* Maybe call finalizer; exit early if resurrected */
- if (type->tp_del) {
- _PyObject_GC_TRACK(self);
- type->tp_del(self);
- if (self->ob_refcnt > 0)
- goto endlabel; /* resurrected */
- else
- _PyObject_GC_UNTRACK(self);
- /* New weakrefs could be created during the finalizer call.
- If this occurs, clear them out without calling their
- finalizers since they might rely on part of the object
- being finalized that has already been destroyed. */
- if (type->tp_weaklistoffset && !base->tp_weaklistoffset) {
- /* Modeled after GET_WEAKREFS_LISTPTR() */
- PyWeakReference **list = (PyWeakReference **) \
- PyObject_GET_WEAKREFS_LISTPTR(self);
- while (*list)
- _PyWeakref_ClearRef(*list);
- }
- }
-
- /* Clear slots up to the nearest base with a different tp_dealloc */
- base = type;
- while ((basedealloc = base->tp_dealloc) == subtype_dealloc) {
- if (base->ob_size)
- clear_slots(base, self);
- base = base->tp_base;
- assert(base);
- }
-
- /* If we added a dict, DECREF it */
- if (type->tp_dictoffset && !base->tp_dictoffset) {
- PyObject **dictptr = _PyObject_GetDictPtr(self);
- if (dictptr != NULL) {
- PyObject *dict = *dictptr;
- if (dict != NULL) {
- Py_DECREF(dict);
- *dictptr = NULL;
- }
- }
- }
-
- /* Call the base tp_dealloc(); first retrack self if
- * basedealloc knows about gc.
- */
- if (PyType_IS_GC(base))
- _PyObject_GC_TRACK(self);
- assert(basedealloc);
- basedealloc(self);
-
- /* Can't reference self beyond this point */
- Py_DECREF(type);
-
- endlabel:
- ++_PyTrash_delete_nesting;
- Py_TRASHCAN_SAFE_END(self);
- --_PyTrash_delete_nesting;
-
- /* Explanation of the weirdness around the trashcan macros:
-
- Q. What do the trashcan macros do?
-
- A. Read the comment titled "Trashcan mechanism" in object.h.
- For one, this explains why there must be a call to GC-untrack
- before the trashcan begin macro. Without understanding the
- trashcan code, the answers to the following questions don't make
- sense.
-
- Q. Why do we GC-untrack before the trashcan and then immediately
- GC-track again afterward?
-
- A. In the case that the base class is GC-aware, the base class
- probably GC-untracks the object. If it does that using the
- UNTRACK macro, this will crash when the object is already
- untracked. Because we don't know what the base class does, the
- only safe thing is to make sure the object is tracked when we
- call the base class dealloc. But... The trashcan begin macro
- requires that the object is *untracked* before it is called. So
- the dance becomes:
-
- GC untrack
- trashcan begin
- GC track
-
- Q. Why did the last question say "immediately GC-track again"?
- It's nowhere near immediately.
-
- A. Because the code *used* to re-track immediately. Bad Idea.
- self has a refcount of 0, and if gc ever gets its hands on it
- (which can happen if any weakref callback gets invoked), it
- looks like trash to gc too, and gc also tries to delete self
- then. But we're already deleting self. Double dealloction is
- a subtle disaster.
-
- Q. Why the bizarre (net-zero) manipulation of
- _PyTrash_delete_nesting around the trashcan macros?
-
- A. Some base classes (e.g. list) also use the trashcan mechanism.
- The following scenario used to be possible:
-
- - suppose the trashcan level is one below the trashcan limit
-
- - subtype_dealloc() is called
-
- - the trashcan limit is not yet reached, so the trashcan level
- is incremented and the code between trashcan begin and end is
- executed
-
- - this destroys much of the object's contents, including its
- slots and __dict__
-
- - basedealloc() is called; this is really list_dealloc(), or
- some other type which also uses the trashcan macros
-
- - the trashcan limit is now reached, so the object is put on the
- trashcan's to-be-deleted-later list
-
- - basedealloc() returns
-
- - subtype_dealloc() decrefs the object's type
-
- - subtype_dealloc() returns
-
- - later, the trashcan code starts deleting the objects from its
- to-be-deleted-later list
-
- - subtype_dealloc() is called *AGAIN* for the same object
-
- - at the very least (if the destroyed slots and __dict__ don't
- cause problems) the object's type gets decref'ed a second
- time, which is *BAD*!!!
-
- The remedy is to make sure that if the code between trashcan
- begin and end in subtype_dealloc() is called, the code between
- trashcan begin and end in basedealloc() will also be called.
- This is done by decrementing the level after passing into the
- trashcan block, and incrementing it just before leaving the
- block.
-
- But now it's possible that a chain of objects consisting solely
- of objects whose deallocator is subtype_dealloc() will defeat
- the trashcan mechanism completely: the decremented level means
- that the effective level never reaches the limit. Therefore, we
- *increment* the level *before* entering the trashcan block, and
- matchingly decrement it after leaving. This means the trashcan
- code will trigger a little early, but that's no big deal.
-
- Q. Are there any live examples of code in need of all this
- complexity?
-
- A. Yes. See SF bug 668433 for code that crashed (when Python was
- compiled in debug mode) before the trashcan level manipulations
- were added. For more discussion, see SF patches 581742, 575073
- and bug 574207.
- */
-}
-
-static PyTypeObject *solid_base(PyTypeObject *type);
-
-/* type test with subclassing support */
-
-int
-PyType_IsSubtype(PyTypeObject *a, PyTypeObject *b)
-{
- PyObject *mro;
-
- if (!(a->tp_flags & Py_TPFLAGS_HAVE_CLASS))
- return b == a || b == &PyBaseObject_Type;
-
- mro = a->tp_mro;
- if (mro != NULL) {
- /* Deal with multiple inheritance without recursion
- by walking the MRO tuple */
- Py_ssize_t i, n;
- assert(PyTuple_Check(mro));
- n = PyTuple_GET_SIZE(mro);
- for (i = 0; i < n; i++) {
- if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b)
- return 1;
- }
- return 0;
- }
- else {
- /* a is not completely initilized yet; follow tp_base */
- do {
- if (a == b)
- return 1;
- a = a->tp_base;
- } while (a != NULL);
- return b == &PyBaseObject_Type;
- }
-}
-
-/* Internal routines to do a method lookup in the type
- without looking in the instance dictionary
- (so we can't use PyObject_GetAttr) but still binding
- it to the instance. The arguments are the object,
- the method name as a C string, and the address of a
- static variable used to cache the interned Python string.
-
- Two variants:
-
- - lookup_maybe() returns NULL without raising an exception
- when the _PyType_Lookup() call fails;
-
- - lookup_method() always raises an exception upon errors.
-*/
-
-static PyObject *
-lookup_maybe(PyObject *self, char *attrstr, PyObject **attrobj)
-{
- PyObject *res;
-
- if (*attrobj == NULL) {
- *attrobj = PyString_InternFromString(attrstr);
- if (*attrobj == NULL)
- return NULL;
- }
- res = _PyType_Lookup(self->ob_type, *attrobj);
- if (res != NULL) {
- descrgetfunc f;
- if ((f = res->ob_type->tp_descr_get) == NULL)
- Py_INCREF(res);
- else
- res = f(res, self, (PyObject *)(self->ob_type));
- }
- return res;
-}
-
-static PyObject *
-lookup_method(PyObject *self, char *attrstr, PyObject **attrobj)
-{
- PyObject *res = lookup_maybe(self, attrstr, attrobj);
- if (res == NULL && !PyErr_Occurred())
- PyErr_SetObject(PyExc_AttributeError, *attrobj);
- return res;
-}
-
-/* A variation of PyObject_CallMethod that uses lookup_method()
- instead of PyObject_GetAttrString(). This uses the same convention
- as lookup_method to cache the interned name string object. */
-
-static PyObject *
-call_method(PyObject *o, char *name, PyObject **nameobj, char *format, ...)
-{
- va_list va;
- PyObject *args, *func = 0, *retval;
- va_start(va, format);
-
- func = lookup_maybe(o, name, nameobj);
- if (func == NULL) {
- va_end(va);
- if (!PyErr_Occurred())
- PyErr_SetObject(PyExc_AttributeError, *nameobj);
- return NULL;
- }
-
- if (format && *format)
- args = Py_VaBuildValue(format, va);
- else
- args = PyTuple_New(0);
-
- va_end(va);
-
- if (args == NULL)
- return NULL;
-
- assert(PyTuple_Check(args));
- retval = PyObject_Call(func, args, NULL);
-
- Py_DECREF(args);
- Py_DECREF(func);
-
- return retval;
-}
-
-/* Clone of call_method() that returns NotImplemented when the lookup fails. */
-
-static PyObject *
-call_maybe(PyObject *o, char *name, PyObject **nameobj, char *format, ...)
-{
- va_list va;
- PyObject *args, *func = 0, *retval;
- va_start(va, format);
-
- func = lookup_maybe(o, name, nameobj);
- if (func == NULL) {
- va_end(va);
- if (!PyErr_Occurred()) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return NULL;
- }
-
- if (format && *format)
- args = Py_VaBuildValue(format, va);
- else
- args = PyTuple_New(0);
-
- va_end(va);
-
- if (args == NULL)
- return NULL;
-
- assert(PyTuple_Check(args));
- retval = PyObject_Call(func, args, NULL);
-
- Py_DECREF(args);
- Py_DECREF(func);
-
- return retval;
-}
-
-static int
-fill_classic_mro(PyObject *mro, PyObject *cls)
-{
- PyObject *bases, *base;
- Py_ssize_t i, n;
-
- assert(PyList_Check(mro));
- assert(PyClass_Check(cls));
- i = PySequence_Contains(mro, cls);
- if (i < 0)
- return -1;
- if (!i) {
- if (PyList_Append(mro, cls) < 0)
- return -1;
- }
- bases = ((PyClassObject *)cls)->cl_bases;
- assert(bases && PyTuple_Check(bases));
- n = PyTuple_GET_SIZE(bases);
- for (i = 0; i < n; i++) {
- base = PyTuple_GET_ITEM(bases, i);
- if (fill_classic_mro(mro, base) < 0)
- return -1;
- }
- return 0;
-}
-
-static PyObject *
-classic_mro(PyObject *cls)
-{
- PyObject *mro;
-
- assert(PyClass_Check(cls));
- mro = PyList_New(0);
- if (mro != NULL) {
- if (fill_classic_mro(mro, cls) == 0)
- return mro;
- Py_DECREF(mro);
- }
- return NULL;
-}
-
-/*
- Method resolution order algorithm C3 described in
- "A Monotonic Superclass Linearization for Dylan",
- by Kim Barrett, Bob Cassel, Paul Haahr,
- David A. Moon, Keith Playford, and P. Tucker Withington.
- (OOPSLA 1996)
-
- Some notes about the rules implied by C3:
-
- No duplicate bases.
- It isn't legal to repeat a class in a list of base classes.
-
- The next three properties are the 3 constraints in "C3".
-
- Local precendece order.
- If A precedes B in C's MRO, then A will precede B in the MRO of all
- subclasses of C.
-
- Monotonicity.
- The MRO of a class must be an extension without reordering of the
- MRO of each of its superclasses.
-
- Extended Precedence Graph (EPG).
- Linearization is consistent if there is a path in the EPG from
- each class to all its successors in the linearization. See
- the paper for definition of EPG.
- */
-
-static int
-tail_contains(PyObject *list, int whence, PyObject *o) {
- Py_ssize_t j, size;
- size = PyList_GET_SIZE(list);
-
- for (j = whence+1; j < size; j++) {
- if (PyList_GET_ITEM(list, j) == o)
- return 1;
- }
- return 0;
-}
-
-static PyObject *
-class_name(PyObject *cls)
-{
- PyObject *name = PyObject_GetAttrString(cls, "__name__");
- if (name == NULL) {
- PyErr_Clear();
- Py_XDECREF(name);
- name = PyObject_Repr(cls);
- }
- if (name == NULL)
- return NULL;
- if (!PyString_Check(name)) {
- Py_DECREF(name);
- return NULL;
- }
- return name;
-}
-
-static int
-check_duplicates(PyObject *list)
-{
- Py_ssize_t i, j, n;
- /* Let's use a quadratic time algorithm,
- assuming that the bases lists is short.
- */
- n = PyList_GET_SIZE(list);
- for (i = 0; i < n; i++) {
- PyObject *o = PyList_GET_ITEM(list, i);
- for (j = i + 1; j < n; j++) {
- if (PyList_GET_ITEM(list, j) == o) {
- o = class_name(o);
- PyErr_Format(PyExc_TypeError,
- "duplicate base class %s",
- o ? PyString_AS_STRING(o) : "?");
- Py_XDECREF(o);
- return -1;
- }
- }
- }
- return 0;
-}
-
-/* Raise a TypeError for an MRO order disagreement.
-
- It's hard to produce a good error message. In the absence of better
- insight into error reporting, report the classes that were candidates
- to be put next into the MRO. There is some conflict between the
- order in which they should be put in the MRO, but it's hard to
- diagnose what constraint can't be satisfied.
-*/
-
-static void
-set_mro_error(PyObject *to_merge, int *remain)
-{
- Py_ssize_t i, n, off, to_merge_size;
- char buf[1000];
- PyObject *k, *v;
- PyObject *set = PyDict_New();
- if (!set) return;
-
- to_merge_size = PyList_GET_SIZE(to_merge);
- for (i = 0; i < to_merge_size; i++) {
- PyObject *L = PyList_GET_ITEM(to_merge, i);
- if (remain[i] < PyList_GET_SIZE(L)) {
- PyObject *c = PyList_GET_ITEM(L, remain[i]);
- if (PyDict_SetItem(set, c, Py_None) < 0) {
- Py_DECREF(set);
- return;
- }
- }
- }
- n = PyDict_Size(set);
-
- off = PyOS_snprintf(buf, sizeof(buf), "Cannot create a \
-consistent method resolution\norder (MRO) for bases");
- i = 0;
- while (PyDict_Next(set, &i, &k, &v) && (size_t)off < sizeof(buf)) {
- PyObject *name = class_name(k);
- off += PyOS_snprintf(buf + off, sizeof(buf) - off, " %s",
- name ? PyString_AS_STRING(name) : "?");
- Py_XDECREF(name);
- if (--n && (size_t)(off+1) < sizeof(buf)) {
- buf[off++] = ',';
- buf[off] = '\0';
- }
- }
- PyErr_SetString(PyExc_TypeError, buf);
- Py_DECREF(set);
-}
-
-static int
-pmerge(PyObject *acc, PyObject* to_merge) {
- Py_ssize_t i, j, to_merge_size, empty_cnt;
- int *remain;
- int ok;
-
- to_merge_size = PyList_GET_SIZE(to_merge);
-
- /* remain stores an index into each sublist of to_merge.
- remain[i] is the index of the next base in to_merge[i]
- that is not included in acc.
- */
- remain = (int *)PyMem_MALLOC(SIZEOF_INT*to_merge_size);
- if (remain == NULL)
- return -1;
- for (i = 0; i < to_merge_size; i++)
- remain[i] = 0;
-
- again:
- empty_cnt = 0;
- for (i = 0; i < to_merge_size; i++) {
- PyObject *candidate;
-
- PyObject *cur_list = PyList_GET_ITEM(to_merge, i);
-
- if (remain[i] >= PyList_GET_SIZE(cur_list)) {
- empty_cnt++;
- continue;
- }
-
- /* Choose next candidate for MRO.
-
- The input sequences alone can determine the choice.
- If not, choose the class which appears in the MRO
- of the earliest direct superclass of the new class.
- */
-
- candidate = PyList_GET_ITEM(cur_list, remain[i]);
- for (j = 0; j < to_merge_size; j++) {
- PyObject *j_lst = PyList_GET_ITEM(to_merge, j);
- if (tail_contains(j_lst, remain[j], candidate)) {
- goto skip; /* continue outer loop */
- }
- }
- ok = PyList_Append(acc, candidate);
- if (ok < 0) {
- PyMem_Free(remain);
- return -1;
- }
- for (j = 0; j < to_merge_size; j++) {
- PyObject *j_lst = PyList_GET_ITEM(to_merge, j);
- if (remain[j] < PyList_GET_SIZE(j_lst) &&
- PyList_GET_ITEM(j_lst, remain[j]) == candidate) {
- remain[j]++;
- }
- }
- goto again;
- skip: ;
- }
-
- if (empty_cnt == to_merge_size) {
- PyMem_FREE(remain);
- return 0;
- }
- set_mro_error(to_merge, remain);
- PyMem_FREE(remain);
- return -1;
-}
-
-static PyObject *
-mro_implementation(PyTypeObject *type)
-{
- Py_ssize_t i, n;
- int ok;
- PyObject *bases, *result;
- PyObject *to_merge, *bases_aslist;
-
- if(type->tp_dict == NULL) {
- if(PyType_Ready(type) < 0)
- return NULL;
- }
-
- /* Find a superclass linearization that honors the constraints
- of the explicit lists of bases and the constraints implied by
- each base class.
-
- to_merge is a list of lists, where each list is a superclass
- linearization implied by a base class. The last element of
- to_merge is the declared list of bases.
- */
-
- bases = type->tp_bases;
- n = PyTuple_GET_SIZE(bases);
-
- to_merge = PyList_New(n+1);
- if (to_merge == NULL)
- return NULL;
-
- for (i = 0; i < n; i++) {
- PyObject *base = PyTuple_GET_ITEM(bases, i);
- PyObject *parentMRO;
- if (PyType_Check(base))
- parentMRO = PySequence_List(
- ((PyTypeObject*)base)->tp_mro);
- else
- parentMRO = classic_mro(base);
- if (parentMRO == NULL) {
- Py_DECREF(to_merge);
- return NULL;
- }
-
- PyList_SET_ITEM(to_merge, i, parentMRO);
- }
-
- bases_aslist = PySequence_List(bases);
- if (bases_aslist == NULL) {
- Py_DECREF(to_merge);
- return NULL;
- }
- /* This is just a basic sanity check. */
- if (check_duplicates(bases_aslist) < 0) {
- Py_DECREF(to_merge);
- Py_DECREF(bases_aslist);
- return NULL;
- }
- PyList_SET_ITEM(to_merge, n, bases_aslist);
-
- result = Py_BuildValue("[O]", (PyObject *)type);
- if (result == NULL) {
- Py_DECREF(to_merge);
- return NULL;
- }
-
- ok = pmerge(result, to_merge);
- Py_DECREF(to_merge);
- if (ok < 0) {
- Py_DECREF(result);
- return NULL;
- }
-
- return result;
-}
-
-static PyObject *
-mro_external(PyObject *self)
-{
- PyTypeObject *type = (PyTypeObject *)self;
-
- return mro_implementation(type);
-}
-
-static int
-mro_internal(PyTypeObject *type)
-{
- PyObject *mro, *result, *tuple;
- int checkit = 0;
-
- if (type->ob_type == &PyType_Type) {
- result = mro_implementation(type);
- }
- else {
- static PyObject *mro_str;
- checkit = 1;
- mro = lookup_method((PyObject *)type, "mro", &mro_str);
- if (mro == NULL)
- return -1;
- result = PyObject_CallObject(mro, NULL);
- Py_DECREF(mro);
- }
- if (result == NULL)
- return -1;
- tuple = PySequence_Tuple(result);
- Py_DECREF(result);
- if (tuple == NULL)
- return -1;
- if (checkit) {
- Py_ssize_t i, len;
- PyObject *cls;
- PyTypeObject *solid;
-
- solid = solid_base(type);
-
- len = PyTuple_GET_SIZE(tuple);
-
- for (i = 0; i < len; i++) {
- PyTypeObject *t;
- cls = PyTuple_GET_ITEM(tuple, i);
- if (PyClass_Check(cls))
- continue;
- else if (!PyType_Check(cls)) {
- PyErr_Format(PyExc_TypeError,
- "mro() returned a non-class ('%.500s')",
- cls->ob_type->tp_name);
- Py_DECREF(tuple);
- return -1;
- }
- t = (PyTypeObject*)cls;
- if (!PyType_IsSubtype(solid, solid_base(t))) {
- PyErr_Format(PyExc_TypeError,
- "mro() returned base with unsuitable layout ('%.500s')",
- t->tp_name);
- Py_DECREF(tuple);
- return -1;
- }
- }
- }
- type->tp_mro = tuple;
- return 0;
-}
-
-
-/* Calculate the best base amongst multiple base classes.
- This is the first one that's on the path to the "solid base". */
-
-static PyTypeObject *
-best_base(PyObject *bases)
-{
- Py_ssize_t i, n;
- PyTypeObject *base, *winner, *candidate, *base_i;
- PyObject *base_proto;
-
- assert(PyTuple_Check(bases));
- n = PyTuple_GET_SIZE(bases);
- assert(n > 0);
- base = NULL;
- winner = NULL;
- for (i = 0; i < n; i++) {
- base_proto = PyTuple_GET_ITEM(bases, i);
- if (PyClass_Check(base_proto))
- continue;
- if (!PyType_Check(base_proto)) {
- PyErr_SetString(
- PyExc_TypeError,
- "bases must be types");
- return NULL;
- }
- base_i = (PyTypeObject *)base_proto;
- if (base_i->tp_dict == NULL) {
- if (PyType_Ready(base_i) < 0)
- return NULL;
- }
- candidate = solid_base(base_i);
- if (winner == NULL) {
- winner = candidate;
- base = base_i;
- }
- else if (PyType_IsSubtype(winner, candidate))
- ;
- else if (PyType_IsSubtype(candidate, winner)) {
- winner = candidate;
- base = base_i;
- }
- else {
- PyErr_SetString(
- PyExc_TypeError,
- "multiple bases have "
- "instance lay-out conflict");
- return NULL;
- }
- }
- if (base == NULL)
- PyErr_SetString(PyExc_TypeError,
- "a new-style class can't have only classic bases");
- return base;
-}
-
-static int
-extra_ivars(PyTypeObject *type, PyTypeObject *base)
-{
- size_t t_size = type->tp_basicsize;
- size_t b_size = base->tp_basicsize;
-
- assert(t_size >= b_size); /* Else type smaller than base! */
- if (type->tp_itemsize || base->tp_itemsize) {
- /* If itemsize is involved, stricter rules */
- return t_size != b_size ||
- type->tp_itemsize != base->tp_itemsize;
- }
- if (type->tp_weaklistoffset && base->tp_weaklistoffset == 0 &&
- type->tp_weaklistoffset + sizeof(PyObject *) == t_size)
- t_size -= sizeof(PyObject *);
- if (type->tp_dictoffset && base->tp_dictoffset == 0 &&
- type->tp_dictoffset + sizeof(PyObject *) == t_size)
- t_size -= sizeof(PyObject *);
-
- return t_size != b_size;
-}
-
-static PyTypeObject *
-solid_base(PyTypeObject *type)
-{
- PyTypeObject *base;
-
- if (type->tp_base)
- base = solid_base(type->tp_base);
- else
- base = &PyBaseObject_Type;
- if (extra_ivars(type, base))
- return type;
- else
- return base;
-}
-
-static void object_dealloc(PyObject *);
-static int object_init(PyObject *, PyObject *, PyObject *);
-static int update_slot(PyTypeObject *, PyObject *);
-static void fixup_slot_dispatchers(PyTypeObject *);
-
-static PyObject *
-subtype_dict(PyObject *obj, void *context)
-{
- PyObject **dictptr = _PyObject_GetDictPtr(obj);
- PyObject *dict;
-
- if (dictptr == NULL) {
- PyErr_SetString(PyExc_AttributeError,
- "This object has no __dict__");
- return NULL;
- }
- dict = *dictptr;
- if (dict == NULL)
- *dictptr = dict = PyDict_New();
- Py_XINCREF(dict);
- return dict;
-}
-
-static int
-subtype_setdict(PyObject *obj, PyObject *value, void *context)
-{
- PyObject **dictptr = _PyObject_GetDictPtr(obj);
- PyObject *dict;
-
- if (dictptr == NULL) {
- PyErr_SetString(PyExc_AttributeError,
- "This object has no __dict__");
- return -1;
- }
- if (value != NULL && !PyDict_Check(value)) {
- PyErr_Format(PyExc_TypeError,
- "__dict__ must be set to a dictionary, "
- "not a '%.200s'", value->ob_type->tp_name);
- return -1;
- }
- dict = *dictptr;
- Py_XINCREF(value);
- *dictptr = value;
- Py_XDECREF(dict);
- return 0;
-}
-
-static PyObject *
-subtype_getweakref(PyObject *obj, void *context)
-{
- PyObject **weaklistptr;
- PyObject *result;
-
- if (obj->ob_type->tp_weaklistoffset == 0) {
- PyErr_SetString(PyExc_AttributeError,
- "This object has no __weakref__");
- return NULL;
- }
- assert(obj->ob_type->tp_weaklistoffset > 0);
- assert(obj->ob_type->tp_weaklistoffset + sizeof(PyObject *) <=
- (size_t)(obj->ob_type->tp_basicsize));
- weaklistptr = (PyObject **)
- ((char *)obj + obj->ob_type->tp_weaklistoffset);
- if (*weaklistptr == NULL)
- result = Py_None;
- else
- result = *weaklistptr;
- Py_INCREF(result);
- return result;
-}
-
-/* Three variants on the subtype_getsets list. */
-
-static PyGetSetDef subtype_getsets_full[] = {
- {"__dict__", subtype_dict, subtype_setdict,
- PyDoc_STR("dictionary for instance variables (if defined)")},
- {"__weakref__", subtype_getweakref, NULL,
- PyDoc_STR("list of weak references to the object (if defined)")},
- {0}
-};
-
-static PyGetSetDef subtype_getsets_dict_only[] = {
- {"__dict__", subtype_dict, subtype_setdict,
- PyDoc_STR("dictionary for instance variables (if defined)")},
- {0}
-};
-
-static PyGetSetDef subtype_getsets_weakref_only[] = {
- {"__weakref__", subtype_getweakref, NULL,
- PyDoc_STR("list of weak references to the object (if defined)")},
- {0}
-};
-
-static int
-valid_identifier(PyObject *s)
-{
- unsigned char *p;
- Py_ssize_t i, n;
-
- if (!PyString_Check(s)) {
- PyErr_Format(PyExc_TypeError,
- "__slots__ items must be strings, not '%.200s'",
- s->ob_type->tp_name);
- return 0;
- }
- p = (unsigned char *) PyString_AS_STRING(s);
- n = PyString_GET_SIZE(s);
- /* We must reject an empty name. As a hack, we bump the
- length to 1 so that the loop will balk on the trailing \0. */
- if (n == 0)
- n = 1;
- for (i = 0; i < n; i++, p++) {
- if (!(i == 0 ? isalpha(*p) : isalnum(*p)) && *p != '_') {
- PyErr_SetString(PyExc_TypeError,
- "__slots__ must be identifiers");
- return 0;
- }
- }
- return 1;
-}
-
-#ifdef Py_USING_UNICODE
-/* Replace Unicode objects in slots. */
-
-static PyObject *
-_unicode_to_string(PyObject *slots, Py_ssize_t nslots)
-{
- PyObject *tmp = NULL;
- PyObject *slot_name, *new_name;
- Py_ssize_t i;
-
- for (i = 0; i < nslots; i++) {
- if (PyUnicode_Check(slot_name = PyTuple_GET_ITEM(slots, i))) {
- if (tmp == NULL) {
- tmp = PySequence_List(slots);
- if (tmp == NULL)
- return NULL;
- }
- new_name = _PyUnicode_AsDefaultEncodedString(slot_name,
- NULL);
- if (new_name == NULL) {
- Py_DECREF(tmp);
- return NULL;
- }
- Py_INCREF(new_name);
- PyList_SET_ITEM(tmp, i, new_name);
- Py_DECREF(slot_name);
- }
- }
- if (tmp != NULL) {
- slots = PyList_AsTuple(tmp);
- Py_DECREF(tmp);
- }
- return slots;
-}
-#endif
-
-static PyObject *
-type_new(PyTypeObject *metatype, PyObject *args, PyObject *kwds)
-{
- PyObject *name, *bases, *dict;
- static char *kwlist[] = {"name", "bases", "dict", 0};
- PyObject *slots, *tmp, *newslots;
- PyTypeObject *type, *base, *tmptype, *winner;
- PyHeapTypeObject *et;
- PyMemberDef *mp;
- Py_ssize_t i, nbases, nslots, slotoffset, add_dict, add_weak;
- int j, may_add_dict, may_add_weak;
-
- assert(args != NULL && PyTuple_Check(args));
- assert(kwds == NULL || PyDict_Check(kwds));
-
- /* Special case: type(x) should return x->ob_type */
- {
- const Py_ssize_t nargs = PyTuple_GET_SIZE(args);
- const Py_ssize_t nkwds = kwds == NULL ? 0 : PyDict_Size(kwds);
-
- if (PyType_CheckExact(metatype) && nargs == 1 && nkwds == 0) {
- PyObject *x = PyTuple_GET_ITEM(args, 0);
- Py_INCREF(x->ob_type);
- return (PyObject *) x->ob_type;
- }
-
- /* SF bug 475327 -- if that didn't trigger, we need 3
- arguments. but PyArg_ParseTupleAndKeywords below may give
- a msg saying type() needs exactly 3. */
- if (nargs + nkwds != 3) {
- PyErr_SetString(PyExc_TypeError,
- "type() takes 1 or 3 arguments");
- return NULL;
- }
- }
-
- /* Check arguments: (name, bases, dict) */
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:type", kwlist,
- &name,
- &PyTuple_Type, &bases,
- &PyDict_Type, &dict))
- return NULL;
-
- /* Determine the proper metatype to deal with this,
- and check for metatype conflicts while we're at it.
- Note that if some other metatype wins to contract,
- it's possible that its instances are not types. */
- nbases = PyTuple_GET_SIZE(bases);
- winner = metatype;
- for (i = 0; i < nbases; i++) {
- tmp = PyTuple_GET_ITEM(bases, i);
- tmptype = tmp->ob_type;
- if (tmptype == &PyClass_Type)
- continue; /* Special case classic classes */
- if (PyType_IsSubtype(winner, tmptype))
- continue;
- if (PyType_IsSubtype(tmptype, winner)) {
- winner = tmptype;
- continue;
- }
- PyErr_SetString(PyExc_TypeError,
- "metaclass conflict: "
- "the metaclass of a derived class "
- "must be a (non-strict) subclass "
- "of the metaclasses of all its bases");
- return NULL;
- }
- if (winner != metatype) {
- if (winner->tp_new != type_new) /* Pass it to the winner */
- return winner->tp_new(winner, args, kwds);
- metatype = winner;
- }
-
- /* Adjust for empty tuple bases */
- if (nbases == 0) {
- bases = PyTuple_Pack(1, &PyBaseObject_Type);
- if (bases == NULL)
- return NULL;
- nbases = 1;
- }
- else
- Py_INCREF(bases);
-
- /* XXX From here until type is allocated, "return NULL" leaks bases! */
-
- /* Calculate best base, and check that all bases are type objects */
- base = best_base(bases);
- if (base == NULL) {
- Py_DECREF(bases);
- return NULL;
- }
- if (!PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
- PyErr_Format(PyExc_TypeError,
- "type '%.100s' is not an acceptable base type",
- base->tp_name);
- Py_DECREF(bases);
- return NULL;
- }
-
- /* Check for a __slots__ sequence variable in dict, and count it */
- slots = PyDict_GetItemString(dict, "__slots__");
- nslots = 0;
- add_dict = 0;
- add_weak = 0;
- may_add_dict = base->tp_dictoffset == 0;
- may_add_weak = base->tp_weaklistoffset == 0 && base->tp_itemsize == 0;
- if (slots == NULL) {
- if (may_add_dict) {
- add_dict++;
- }
- if (may_add_weak) {
- add_weak++;
- }
- }
- else {
- /* Have slots */
-
- /* Make it into a tuple */
- if (PyString_Check(slots))
- slots = PyTuple_Pack(1, slots);
- else
- slots = PySequence_Tuple(slots);
- if (slots == NULL) {
- Py_DECREF(bases);
- return NULL;
- }
- assert(PyTuple_Check(slots));
-
- /* Are slots allowed? */
- nslots = PyTuple_GET_SIZE(slots);
- if (nslots > 0 && base->tp_itemsize != 0) {
- PyErr_Format(PyExc_TypeError,
- "nonempty __slots__ "
- "not supported for subtype of '%s'",
- base->tp_name);
- bad_slots:
- Py_DECREF(bases);
- Py_DECREF(slots);
- return NULL;
- }
-
-#ifdef Py_USING_UNICODE
- tmp = _unicode_to_string(slots, nslots);
- if (tmp == NULL)
- goto bad_slots;
- if (tmp != slots) {
- Py_DECREF(slots);
- slots = tmp;
- }
-#endif
- /* Check for valid slot names and two special cases */
- for (i = 0; i < nslots; i++) {
- PyObject *tmp = PyTuple_GET_ITEM(slots, i);
- char *s;
- if (!valid_identifier(tmp))
- goto bad_slots;
- assert(PyString_Check(tmp));
- s = PyString_AS_STRING(tmp);
- if (strcmp(s, "__dict__") == 0) {
- if (!may_add_dict || add_dict) {
- PyErr_SetString(PyExc_TypeError,
- "__dict__ slot disallowed: "
- "we already got one");
- goto bad_slots;
- }
- add_dict++;
- }
- if (strcmp(s, "__weakref__") == 0) {
- if (!may_add_weak || add_weak) {
- PyErr_SetString(PyExc_TypeError,
- "__weakref__ slot disallowed: "
- "either we already got one, "
- "or __itemsize__ != 0");
- goto bad_slots;
- }
- add_weak++;
- }
- }
-
- /* Copy slots into yet another tuple, demangling names */
- newslots = PyTuple_New(nslots - add_dict - add_weak);
- if (newslots == NULL)
- goto bad_slots;
- for (i = j = 0; i < nslots; i++) {
- char *s;
- tmp = PyTuple_GET_ITEM(slots, i);
- s = PyString_AS_STRING(tmp);
- if ((add_dict && strcmp(s, "__dict__") == 0) ||
- (add_weak && strcmp(s, "__weakref__") == 0))
- continue;
- tmp =_Py_Mangle(name, tmp);
- if (!tmp)
- goto bad_slots;
- PyTuple_SET_ITEM(newslots, j, tmp);
- j++;
- }
- assert(j == nslots - add_dict - add_weak);
- nslots = j;
- Py_DECREF(slots);
- slots = newslots;
-
- /* Secondary bases may provide weakrefs or dict */
- if (nbases > 1 &&
- ((may_add_dict && !add_dict) ||
- (may_add_weak && !add_weak))) {
- for (i = 0; i < nbases; i++) {
- tmp = PyTuple_GET_ITEM(bases, i);
- if (tmp == (PyObject *)base)
- continue; /* Skip primary base */
- if (PyClass_Check(tmp)) {
- /* Classic base class provides both */
- if (may_add_dict && !add_dict)
- add_dict++;
- if (may_add_weak && !add_weak)
- add_weak++;
- break;
- }
- assert(PyType_Check(tmp));
- tmptype = (PyTypeObject *)tmp;
- if (may_add_dict && !add_dict &&
- tmptype->tp_dictoffset != 0)
- add_dict++;
- if (may_add_weak && !add_weak &&
- tmptype->tp_weaklistoffset != 0)
- add_weak++;
- if (may_add_dict && !add_dict)
- continue;
- if (may_add_weak && !add_weak)
- continue;
- /* Nothing more to check */
- break;
- }
- }
- }
-
- /* XXX From here until type is safely allocated,
- "return NULL" may leak slots! */
-
- /* Allocate the type object */
- type = (PyTypeObject *)metatype->tp_alloc(metatype, nslots);
- if (type == NULL) {
- Py_XDECREF(slots);
- Py_DECREF(bases);
- return NULL;
- }
-
- /* Keep name and slots alive in the extended type object */
- et = (PyHeapTypeObject *)type;
- Py_INCREF(name);
- et->ht_name = name;
- et->ht_slots = slots;
-
- /* Initialize tp_flags */
- type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE |
- Py_TPFLAGS_BASETYPE;
- if (base->tp_flags & Py_TPFLAGS_HAVE_GC)
- type->tp_flags |= Py_TPFLAGS_HAVE_GC;
-
- /* It's a new-style number unless it specifically inherits any
- old-style numeric behavior */
- if ((base->tp_flags & Py_TPFLAGS_CHECKTYPES) ||
- (base->tp_as_number == NULL))
- type->tp_flags |= Py_TPFLAGS_CHECKTYPES;
-
- /* Initialize essential fields */
- type->tp_as_number = &et->as_number;
- type->tp_as_sequence = &et->as_sequence;
- type->tp_as_mapping = &et->as_mapping;
- type->tp_as_buffer = &et->as_buffer;
- type->tp_name = PyString_AS_STRING(name);
-
- /* Set tp_base and tp_bases */
- type->tp_bases = bases;
- Py_INCREF(base);
- type->tp_base = base;
-
- /* Initialize tp_dict from passed-in dict */
- type->tp_dict = dict = PyDict_Copy(dict);
- if (dict == NULL) {
- Py_DECREF(type);
- return NULL;
- }
-
- /* Set __module__ in the dict */
- if (PyDict_GetItemString(dict, "__module__") == NULL) {
- tmp = PyEval_GetGlobals();
- if (tmp != NULL) {
- tmp = PyDict_GetItemString(tmp, "__name__");
- if (tmp != NULL) {
- if (PyDict_SetItemString(dict, "__module__",
- tmp) < 0)
- return NULL;
- }
- }
- }
-
- /* Set tp_doc to a copy of dict['__doc__'], if the latter is there
- and is a string. The __doc__ accessor will first look for tp_doc;
- if that fails, it will still look into __dict__.
- */
- {
- PyObject *doc = PyDict_GetItemString(dict, "__doc__");
- if (doc != NULL && PyString_Check(doc)) {
- const size_t n = (size_t)PyString_GET_SIZE(doc);
- char *tp_doc = (char *)PyObject_MALLOC(n+1);
- if (tp_doc == NULL) {
- Py_DECREF(type);
- return NULL;
- }
- memcpy(tp_doc, PyString_AS_STRING(doc), n+1);
- type->tp_doc = tp_doc;
- }
- }
-
- /* Special-case __new__: if it's a plain function,
- make it a static function */
- tmp = PyDict_GetItemString(dict, "__new__");
- if (tmp != NULL && PyFunction_Check(tmp)) {
- tmp = PyStaticMethod_New(tmp);
- if (tmp == NULL) {
- Py_DECREF(type);
- return NULL;
- }
- PyDict_SetItemString(dict, "__new__", tmp);
- Py_DECREF(tmp);
- }
-
- /* Add descriptors for custom slots from __slots__, or for __dict__ */
- mp = PyHeapType_GET_MEMBERS(et);
- slotoffset = base->tp_basicsize;
- if (slots != NULL) {
- for (i = 0; i < nslots; i++, mp++) {
- mp->name = PyString_AS_STRING(
- PyTuple_GET_ITEM(slots, i));
- mp->type = T_OBJECT_EX;
- mp->offset = slotoffset;
-
- /* __dict__ and __weakref__ are already filtered out */
- assert(strcmp(mp->name, "__dict__") != 0);
- assert(strcmp(mp->name, "__weakref__") != 0);
-
- slotoffset += sizeof(PyObject *);
- }
- }
- if (add_dict) {
- if (base->tp_itemsize)
- type->tp_dictoffset = -(long)sizeof(PyObject *);
- else
- type->tp_dictoffset = slotoffset;
- slotoffset += sizeof(PyObject *);
- }
- if (add_weak) {
- assert(!base->tp_itemsize);
- type->tp_weaklistoffset = slotoffset;
- slotoffset += sizeof(PyObject *);
- }
- type->tp_basicsize = slotoffset;
- type->tp_itemsize = base->tp_itemsize;
- type->tp_members = PyHeapType_GET_MEMBERS(et);
-
- if (type->tp_weaklistoffset && type->tp_dictoffset)
- type->tp_getset = subtype_getsets_full;
- else if (type->tp_weaklistoffset && !type->tp_dictoffset)
- type->tp_getset = subtype_getsets_weakref_only;
- else if (!type->tp_weaklistoffset && type->tp_dictoffset)
- type->tp_getset = subtype_getsets_dict_only;
- else
- type->tp_getset = NULL;
-
- /* Special case some slots */
- if (type->tp_dictoffset != 0 || nslots > 0) {
- if (base->tp_getattr == NULL && base->tp_getattro == NULL)
- type->tp_getattro = PyObject_GenericGetAttr;
- if (base->tp_setattr == NULL && base->tp_setattro == NULL)
- type->tp_setattro = PyObject_GenericSetAttr;
- }
- type->tp_dealloc = subtype_dealloc;
-
- /* Enable GC unless there are really no instance variables possible */
- if (!(type->tp_basicsize == sizeof(PyObject) &&
- type->tp_itemsize == 0))
- type->tp_flags |= Py_TPFLAGS_HAVE_GC;
-
- /* Always override allocation strategy to use regular heap */
- type->tp_alloc = PyType_GenericAlloc;
- if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
- type->tp_free = PyObject_GC_Del;
- type->tp_traverse = subtype_traverse;
- type->tp_clear = subtype_clear;
- }
- else
- type->tp_free = PyObject_Del;
-
- /* Initialize the rest */
- if (PyType_Ready(type) < 0) {
- Py_DECREF(type);
- return NULL;
- }
-
- /* Put the proper slots in place */
- fixup_slot_dispatchers(type);
-
- return (PyObject *)type;
-}
-
-/* Internal API to look for a name through the MRO.
- This returns a borrowed reference, and doesn't set an exception! */
-PyObject *
-_PyType_Lookup(PyTypeObject *type, PyObject *name)
-{
- Py_ssize_t i, n;
- PyObject *mro, *res, *base, *dict;
-
- /* Look in tp_dict of types in MRO */
- mro = type->tp_mro;
-
- /* If mro is NULL, the type is either not yet initialized
- by PyType_Ready(), or already cleared by type_clear().
- Either way the safest thing to do is to return NULL. */
- if (mro == NULL)
- return NULL;
-
- assert(PyTuple_Check(mro));
- n = PyTuple_GET_SIZE(mro);
- for (i = 0; i < n; i++) {
- base = PyTuple_GET_ITEM(mro, i);
- if (PyClass_Check(base))
- dict = ((PyClassObject *)base)->cl_dict;
- else {
- assert(PyType_Check(base));
- dict = ((PyTypeObject *)base)->tp_dict;
- }
- assert(dict && PyDict_Check(dict));
- res = PyDict_GetItem(dict, name);
- if (res != NULL)
- return res;
- }
- return NULL;
-}
-
-/* This is similar to PyObject_GenericGetAttr(),
- but uses _PyType_Lookup() instead of just looking in type->tp_dict. */
-static PyObject *
-type_getattro(PyTypeObject *type, PyObject *name)
-{
- PyTypeObject *metatype = type->ob_type;
- PyObject *meta_attribute, *attribute;
- descrgetfunc meta_get;
-
- /* Initialize this type (we'll assume the metatype is initialized) */
- if (type->tp_dict == NULL) {
- if (PyType_Ready(type) < 0)
- return NULL;
- }
-
- /* No readable descriptor found yet */
- meta_get = NULL;
-
- /* Look for the attribute in the metatype */
- meta_attribute = _PyType_Lookup(metatype, name);
-
- if (meta_attribute != NULL) {
- meta_get = meta_attribute->ob_type->tp_descr_get;
-
- if (meta_get != NULL && PyDescr_IsData(meta_attribute)) {
- /* Data descriptors implement tp_descr_set to intercept
- * writes. Assume the attribute is not overridden in
- * type's tp_dict (and bases): call the descriptor now.
- */
- return meta_get(meta_attribute, (PyObject *)type,
- (PyObject *)metatype);
- }
- Py_INCREF(meta_attribute);
- }
-
- /* No data descriptor found on metatype. Look in tp_dict of this
- * type and its bases */
- attribute = _PyType_Lookup(type, name);
- if (attribute != NULL) {
- /* Implement descriptor functionality, if any */
- descrgetfunc local_get = attribute->ob_type->tp_descr_get;
-
- Py_XDECREF(meta_attribute);
-
- if (local_get != NULL) {
- /* NULL 2nd argument indicates the descriptor was
- * found on the target object itself (or a base) */
- return local_get(attribute, (PyObject *)NULL,
- (PyObject *)type);
- }
-
- Py_INCREF(attribute);
- return attribute;
- }
-
- /* No attribute found in local __dict__ (or bases): use the
- * descriptor from the metatype, if any */
- if (meta_get != NULL) {
- PyObject *res;
- res = meta_get(meta_attribute, (PyObject *)type,
- (PyObject *)metatype);
- Py_DECREF(meta_attribute);
- return res;
- }
-
- /* If an ordinary attribute was found on the metatype, return it now */
- if (meta_attribute != NULL) {
- return meta_attribute;
- }
-
- /* Give up */
- PyErr_Format(PyExc_AttributeError,
- "type object '%.50s' has no attribute '%.400s'",
- type->tp_name, PyString_AS_STRING(name));
- return NULL;
-}
-
-static int
-type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
-{
- if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
- PyErr_Format(
- PyExc_TypeError,
- "can't set attributes of built-in/extension type '%s'",
- type->tp_name);
- return -1;
- }
- /* XXX Example of how I expect this to be used...
- if (update_subclasses(type, name, invalidate_cache, NULL) < 0)
- return -1;
- */
- if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
- return -1;
- return update_slot(type, name);
-}
-
-static void
-type_dealloc(PyTypeObject *type)
-{
- PyHeapTypeObject *et;
-
- /* Assert this is a heap-allocated type object */
- assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
- _PyObject_GC_UNTRACK(type);
- PyObject_ClearWeakRefs((PyObject *)type);
- et = (PyHeapTypeObject *)type;
- Py_XDECREF(type->tp_base);
- Py_XDECREF(type->tp_dict);
- Py_XDECREF(type->tp_bases);
- Py_XDECREF(type->tp_mro);
- Py_XDECREF(type->tp_cache);
- Py_XDECREF(type->tp_subclasses);
- /* A type's tp_doc is heap allocated, unlike the tp_doc slots
- * of most other objects. It's okay to cast it to char *.
- */
- PyObject_Free((char *)type->tp_doc);
- Py_XDECREF(et->ht_name);
- Py_XDECREF(et->ht_slots);
- type->ob_type->tp_free((PyObject *)type);
-}
-
-static PyObject *
-type_subclasses(PyTypeObject *type, PyObject *args_ignored)
-{
- PyObject *list, *raw, *ref;
- Py_ssize_t i, n;
-
- list = PyList_New(0);
- if (list == NULL)
- return NULL;
- raw = type->tp_subclasses;
- if (raw == NULL)
- return list;
- assert(PyList_Check(raw));
- n = PyList_GET_SIZE(raw);
- for (i = 0; i < n; i++) {
- ref = PyList_GET_ITEM(raw, i);
- assert(PyWeakref_CheckRef(ref));
- ref = PyWeakref_GET_OBJECT(ref);
- if (ref != Py_None) {
- if (PyList_Append(list, ref) < 0) {
- Py_DECREF(list);
- return NULL;
- }
- }
- }
- return list;
-}
-
-static PyMethodDef type_methods[] = {
- {"mro", (PyCFunction)mro_external, METH_NOARGS,
- PyDoc_STR("mro() -> list\nreturn a type's method resolution order")},
- {"__subclasses__", (PyCFunction)type_subclasses, METH_NOARGS,
- PyDoc_STR("__subclasses__() -> list of immediate subclasses")},
- {0}
-};
-
-PyDoc_STRVAR(type_doc,
-"type(object) -> the object's type\n"
-"type(name, bases, dict) -> a new type");
-
-static int
-type_traverse(PyTypeObject *type, visitproc visit, void *arg)
-{
- /* Because of type_is_gc(), the collector only calls this
- for heaptypes. */
- assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
-
- Py_VISIT(type->tp_dict);
- Py_VISIT(type->tp_cache);
- Py_VISIT(type->tp_mro);
- Py_VISIT(type->tp_bases);
- Py_VISIT(type->tp_base);
-
- /* There's no need to visit type->tp_subclasses or
- ((PyHeapTypeObject *)type)->ht_slots, because they can't be involved
- in cycles; tp_subclasses is a list of weak references,
- and slots is a tuple of strings. */
-
- return 0;
-}
-
-static int
-type_clear(PyTypeObject *type)
-{
- /* Because of type_is_gc(), the collector only calls this
- for heaptypes. */
- assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
-
- /* The only field we need to clear is tp_mro, which is part of a
- hard cycle (its first element is the class itself) that won't
- be broken otherwise (it's a tuple and tuples don't have a
- tp_clear handler). None of the other fields need to be
- cleared, and here's why:
-
- tp_dict:
- It is a dict, so the collector will call its tp_clear.
-
- tp_cache:
- Not used; if it were, it would be a dict.
-
- tp_bases, tp_base:
- If these are involved in a cycle, there must be at least
- one other, mutable object in the cycle, e.g. a base
- class's dict; the cycle will be broken that way.
-
- tp_subclasses:
- A list of weak references can't be part of a cycle; and
- lists have their own tp_clear.
-
- slots (in PyHeapTypeObject):
- A tuple of strings can't be part of a cycle.
- */
-
- Py_CLEAR(type->tp_mro);
-
- return 0;
-}
-
-static int
-type_is_gc(PyTypeObject *type)
-{
- return type->tp_flags & Py_TPFLAGS_HEAPTYPE;
-}
-
-PyTypeObject PyType_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "type", /* tp_name */
- sizeof(PyHeapTypeObject), /* tp_basicsize */
- sizeof(PyMemberDef), /* tp_itemsize */
- (destructor)type_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- type_compare, /* tp_compare */
- (reprfunc)type_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- (hashfunc)_Py_HashPointer, /* tp_hash */
- (ternaryfunc)type_call, /* tp_call */
- 0, /* tp_str */
- (getattrofunc)type_getattro, /* tp_getattro */
- (setattrofunc)type_setattro, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- type_doc, /* tp_doc */
- (traverseproc)type_traverse, /* tp_traverse */
- (inquiry)type_clear, /* tp_clear */
- 0, /* tp_richcompare */
- offsetof(PyTypeObject, tp_weaklist), /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- type_methods, /* tp_methods */
- type_members, /* tp_members */
- type_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- offsetof(PyTypeObject, tp_dict), /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- type_new, /* tp_new */
- PyObject_GC_Del, /* tp_free */
- (inquiry)type_is_gc, /* tp_is_gc */
-};
-
-
-/* The base type of all types (eventually)... except itself. */
-
-static int
-object_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- return 0;
-}
-
-/* If we don't have a tp_new for a new-style class, new will use this one.
- Therefore this should take no arguments/keywords. However, this new may
- also be inherited by objects that define a tp_init but no tp_new. These
- objects WILL pass argumets to tp_new, because it gets the same args as
- tp_init. So only allow arguments if we aren't using the default init, in
- which case we expect init to handle argument parsing. */
-static PyObject *
-object_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- if (type->tp_init == object_init && (PyTuple_GET_SIZE(args) ||
- (kwds && PyDict_Check(kwds) && PyDict_Size(kwds)))) {
- PyErr_SetString(PyExc_TypeError,
- "default __new__ takes no parameters");
- return NULL;
- }
- return type->tp_alloc(type, 0);
-}
-
-static void
-object_dealloc(PyObject *self)
-{
- self->ob_type->tp_free(self);
-}
-
-static PyObject *
-object_repr(PyObject *self)
-{
- PyTypeObject *type;
- PyObject *mod, *name, *rtn;
-
- type = self->ob_type;
- mod = type_module(type, NULL);
- if (mod == NULL)
- PyErr_Clear();
- else if (!PyString_Check(mod)) {
- Py_DECREF(mod);
- mod = NULL;
- }
- name = type_name(type, NULL);
- if (name == NULL)
- return NULL;
- if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__"))
- rtn = PyString_FromFormat("<%s.%s object at %p>",
- PyString_AS_STRING(mod),
- PyString_AS_STRING(name),
- self);
- else
- rtn = PyString_FromFormat("<%s object at %p>",
- type->tp_name, self);
- Py_XDECREF(mod);
- Py_DECREF(name);
- return rtn;
-}
-
-static PyObject *
-object_str(PyObject *self)
-{
- unaryfunc f;
-
- f = self->ob_type->tp_repr;
- if (f == NULL)
- f = object_repr;
- return f(self);
-}
-
-static long
-object_hash(PyObject *self)
-{
- return _Py_HashPointer(self);
-}
-
-static PyObject *
-object_get_class(PyObject *self, void *closure)
-{
- Py_INCREF(self->ob_type);
- return (PyObject *)(self->ob_type);
-}
-
-static int
-equiv_structs(PyTypeObject *a, PyTypeObject *b)
-{
- return a == b ||
- (a != NULL &&
- b != NULL &&
- a->tp_basicsize == b->tp_basicsize &&
- a->tp_itemsize == b->tp_itemsize &&
- a->tp_dictoffset == b->tp_dictoffset &&
- a->tp_weaklistoffset == b->tp_weaklistoffset &&
- ((a->tp_flags & Py_TPFLAGS_HAVE_GC) ==
- (b->tp_flags & Py_TPFLAGS_HAVE_GC)));
-}
-
-static int
-same_slots_added(PyTypeObject *a, PyTypeObject *b)
-{
- PyTypeObject *base = a->tp_base;
- Py_ssize_t size;
-
- if (base != b->tp_base)
- return 0;
- if (equiv_structs(a, base) && equiv_structs(b, base))
- return 1;
- size = base->tp_basicsize;
- if (a->tp_dictoffset == size && b->tp_dictoffset == size)
- size += sizeof(PyObject *);
- if (a->tp_weaklistoffset == size && b->tp_weaklistoffset == size)
- size += sizeof(PyObject *);
- return size == a->tp_basicsize && size == b->tp_basicsize;
-}
-
-static int
-compatible_for_assignment(PyTypeObject* oldto, PyTypeObject* newto, char* attr)
-{
- PyTypeObject *newbase, *oldbase;
-
- if (newto->tp_dealloc != oldto->tp_dealloc ||
- newto->tp_free != oldto->tp_free)
- {
- PyErr_Format(PyExc_TypeError,
- "%s assignment: "
- "'%s' deallocator differs from '%s'",
- attr,
- newto->tp_name,
- oldto->tp_name);
- return 0;
- }
- newbase = newto;
- oldbase = oldto;
- while (equiv_structs(newbase, newbase->tp_base))
- newbase = newbase->tp_base;
- while (equiv_structs(oldbase, oldbase->tp_base))
- oldbase = oldbase->tp_base;
- if (newbase != oldbase &&
- (newbase->tp_base != oldbase->tp_base ||
- !same_slots_added(newbase, oldbase))) {
- PyErr_Format(PyExc_TypeError,
- "%s assignment: "
- "'%s' object layout differs from '%s'",
- attr,
- newto->tp_name,
- oldto->tp_name);
- return 0;
- }
-
- return 1;
-}
-
-static int
-object_set_class(PyObject *self, PyObject *value, void *closure)
-{
- PyTypeObject *oldto = self->ob_type;
- PyTypeObject *newto;
-
- if (value == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "can't delete __class__ attribute");
- return -1;
- }
- if (!PyType_Check(value)) {
- PyErr_Format(PyExc_TypeError,
- "__class__ must be set to new-style class, not '%s' object",
- value->ob_type->tp_name);
- return -1;
- }
- newto = (PyTypeObject *)value;
- if (!(newto->tp_flags & Py_TPFLAGS_HEAPTYPE) ||
- !(oldto->tp_flags & Py_TPFLAGS_HEAPTYPE))
- {
- PyErr_Format(PyExc_TypeError,
- "__class__ assignment: only for heap types");
- return -1;
- }
- if (compatible_for_assignment(newto, oldto, "__class__")) {
- Py_INCREF(newto);
- self->ob_type = newto;
- Py_DECREF(oldto);
- return 0;
- }
- else {
- return -1;
- }
-}
-
-static PyGetSetDef object_getsets[] = {
- {"__class__", object_get_class, object_set_class,
- PyDoc_STR("the object's class")},
- {0}
-};
-
-
-/* Stuff to implement __reduce_ex__ for pickle protocols >= 2.
- We fall back to helpers in copy_reg for:
- - pickle protocols < 2
- - calculating the list of slot names (done only once per class)
- - the __newobj__ function (which is used as a token but never called)
-*/
-
-static PyObject *
-import_copy_reg(void)
-{
- static PyObject *copy_reg_str;
-
- if (!copy_reg_str) {
- copy_reg_str = PyString_InternFromString("copy_reg");
- if (copy_reg_str == NULL)
- return NULL;
- }
-
- return PyImport_Import(copy_reg_str);
-}
-
-static PyObject *
-slotnames(PyObject *cls)
-{
- PyObject *clsdict;
- PyObject *copy_reg;
- PyObject *slotnames;
-
- if (!PyType_Check(cls)) {
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- clsdict = ((PyTypeObject *)cls)->tp_dict;
- slotnames = PyDict_GetItemString(clsdict, "__slotnames__");
- if (slotnames != NULL && PyList_Check(slotnames)) {
- Py_INCREF(slotnames);
- return slotnames;
- }
-
- copy_reg = import_copy_reg();
- if (copy_reg == NULL)
- return NULL;
-
- slotnames = PyObject_CallMethod(copy_reg, "_slotnames", "O", cls);
- Py_DECREF(copy_reg);
- if (slotnames != NULL &&
- slotnames != Py_None &&
- !PyList_Check(slotnames))
- {
- PyErr_SetString(PyExc_TypeError,
- "copy_reg._slotnames didn't return a list or None");
- Py_DECREF(slotnames);
- slotnames = NULL;
- }
-
- return slotnames;
-}
-
-static PyObject *
-reduce_2(PyObject *obj)
-{
- PyObject *cls, *getnewargs;
- PyObject *args = NULL, *args2 = NULL;
- PyObject *getstate = NULL, *state = NULL, *names = NULL;
- PyObject *slots = NULL, *listitems = NULL, *dictitems = NULL;
- PyObject *copy_reg = NULL, *newobj = NULL, *res = NULL;
- Py_ssize_t i, n;
-
- cls = PyObject_GetAttrString(obj, "__class__");
- if (cls == NULL)
- return NULL;
-
- getnewargs = PyObject_GetAttrString(obj, "__getnewargs__");
- if (getnewargs != NULL) {
- args = PyObject_CallObject(getnewargs, NULL);
- Py_DECREF(getnewargs);
- if (args != NULL && !PyTuple_Check(args)) {
- PyErr_Format(PyExc_TypeError,
- "__getnewargs__ should return a tuple, "
- "not '%.200s'", args->ob_type->tp_name);
- goto end;
- }
- }
- else {
- PyErr_Clear();
- args = PyTuple_New(0);
- }
- if (args == NULL)
- goto end;
-
- getstate = PyObject_GetAttrString(obj, "__getstate__");
- if (getstate != NULL) {
- state = PyObject_CallObject(getstate, NULL);
- Py_DECREF(getstate);
- if (state == NULL)
- goto end;
- }
- else {
- PyErr_Clear();
- state = PyObject_GetAttrString(obj, "__dict__");
- if (state == NULL) {
- PyErr_Clear();
- state = Py_None;
- Py_INCREF(state);
- }
- names = slotnames(cls);
- if (names == NULL)
- goto end;
- if (names != Py_None) {
- assert(PyList_Check(names));
- slots = PyDict_New();
- if (slots == NULL)
- goto end;
- n = 0;
- /* Can't pre-compute the list size; the list
- is stored on the class so accessible to other
- threads, which may be run by DECREF */
- for (i = 0; i < PyList_GET_SIZE(names); i++) {
- PyObject *name, *value;
- name = PyList_GET_ITEM(names, i);
- value = PyObject_GetAttr(obj, name);
- if (value == NULL)
- PyErr_Clear();
- else {
- int err = PyDict_SetItem(slots, name,
- value);
- Py_DECREF(value);
- if (err)
- goto end;
- n++;
- }
- }
- if (n) {
- state = Py_BuildValue("(NO)", state, slots);
- if (state == NULL)
- goto end;
- }
- }
- }
-
- if (!PyList_Check(obj)) {
- listitems = Py_None;
- Py_INCREF(listitems);
- }
- else {
- listitems = PyObject_GetIter(obj);
- if (listitems == NULL)
- goto end;
- }
-
- if (!PyDict_Check(obj)) {
- dictitems = Py_None;
- Py_INCREF(dictitems);
- }
- else {
- dictitems = PyObject_CallMethod(obj, "iteritems", "");
- if (dictitems == NULL)
- goto end;
- }
-
- copy_reg = import_copy_reg();
- if (copy_reg == NULL)
- goto end;
- newobj = PyObject_GetAttrString(copy_reg, "__newobj__");
- if (newobj == NULL)
- goto end;
-
- n = PyTuple_GET_SIZE(args);
- args2 = PyTuple_New(n+1);
- if (args2 == NULL)
- goto end;
- PyTuple_SET_ITEM(args2, 0, cls);
- cls = NULL;
- for (i = 0; i < n; i++) {
- PyObject *v = PyTuple_GET_ITEM(args, i);
- Py_INCREF(v);
- PyTuple_SET_ITEM(args2, i+1, v);
- }
-
- res = PyTuple_Pack(5, newobj, args2, state, listitems, dictitems);
-
- end:
- Py_XDECREF(cls);
- Py_XDECREF(args);
- Py_XDECREF(args2);
- Py_XDECREF(slots);
- Py_XDECREF(state);
- Py_XDECREF(names);
- Py_XDECREF(listitems);
- Py_XDECREF(dictitems);
- Py_XDECREF(copy_reg);
- Py_XDECREF(newobj);
- return res;
-}
-
-/*
- * There were two problems when object.__reduce__ and object.__reduce_ex__
- * were implemented in the same function:
- * - trying to pickle an object with a custom __reduce__ method that
- * fell back to object.__reduce__ in certain circumstances led to
- * infinite recursion at Python level and eventual RuntimeError.
- * - Pickling objects that lied about their type by overwriting the
- * __class__ descriptor could lead to infinite recursion at C level
- * and eventual segfault.
- *
- * Because of backwards compatibility, the two methods still have to
- * behave in the same way, even if this is not required by the pickle
- * protocol. This common functionality was moved to the _common_reduce
- * function.
- */
-static PyObject *
-_common_reduce(PyObject *self, int proto)
-{
- PyObject *copy_reg, *res;
-
- if (proto >= 2)
- return reduce_2(self);
-
- copy_reg = import_copy_reg();
- if (!copy_reg)
- return NULL;
-
- res = PyEval_CallMethod(copy_reg, "_reduce_ex", "(Oi)", self, proto);
- Py_DECREF(copy_reg);
-
- return res;
-}
-
-static PyObject *
-object_reduce(PyObject *self, PyObject *args)
-{
- int proto = 0;
-
- if (!PyArg_ParseTuple(args, "|i:__reduce__", &proto))
- return NULL;
-
- return _common_reduce(self, proto);
-}
-
-static PyObject *
-object_reduce_ex(PyObject *self, PyObject *args)
-{
- PyObject *reduce, *res;
- int proto = 0;
-
- if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto))
- return NULL;
-
- reduce = PyObject_GetAttrString(self, "__reduce__");
- if (reduce == NULL)
- PyErr_Clear();
- else {
- PyObject *cls, *clsreduce, *objreduce;
- int override;
- cls = PyObject_GetAttrString(self, "__class__");
- if (cls == NULL) {
- Py_DECREF(reduce);
- return NULL;
- }
- clsreduce = PyObject_GetAttrString(cls, "__reduce__");
- Py_DECREF(cls);
- if (clsreduce == NULL) {
- Py_DECREF(reduce);
- return NULL;
- }
- objreduce = PyDict_GetItemString(PyBaseObject_Type.tp_dict,
- "__reduce__");
- override = (clsreduce != objreduce);
- Py_DECREF(clsreduce);
- if (override) {
- res = PyObject_CallObject(reduce, NULL);
- Py_DECREF(reduce);
- return res;
- }
- else
- Py_DECREF(reduce);
- }
-
- return _common_reduce(self, proto);
-}
-
-static PyMethodDef object_methods[] = {
- {"__reduce_ex__", object_reduce_ex, METH_VARARGS,
- PyDoc_STR("helper for pickle")},
- {"__reduce__", object_reduce, METH_VARARGS,
- PyDoc_STR("helper for pickle")},
- {0}
-};
-
-
-PyTypeObject PyBaseObject_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "object", /* tp_name */
- sizeof(PyObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- object_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- object_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- object_hash, /* tp_hash */
- 0, /* tp_call */
- object_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- PyObject_GenericSetAttr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- PyDoc_STR("The most base type"), /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- object_methods, /* tp_methods */
- 0, /* tp_members */
- object_getsets, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- object_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- object_new, /* tp_new */
- PyObject_Del, /* tp_free */
-};
-
-
-/* Initialize the __dict__ in a type object */
-
-static int
-add_methods(PyTypeObject *type, PyMethodDef *meth)
-{
- PyObject *dict = type->tp_dict;
-
- for (; meth->ml_name != NULL; meth++) {
- PyObject *descr;
- if (PyDict_GetItemString(dict, meth->ml_name) &&
- !(meth->ml_flags & METH_COEXIST))
- continue;
- if (meth->ml_flags & METH_CLASS) {
- if (meth->ml_flags & METH_STATIC) {
- PyErr_SetString(PyExc_ValueError,
- "method cannot be both class and static");
- return -1;
- }
- descr = PyDescr_NewClassMethod(type, meth);
- }
- else if (meth->ml_flags & METH_STATIC) {
- PyObject *cfunc = PyCFunction_New(meth, NULL);
- if (cfunc == NULL)
- return -1;
- descr = PyStaticMethod_New(cfunc);
- Py_DECREF(cfunc);
- }
- else {
- descr = PyDescr_NewMethod(type, meth);
- }
- if (descr == NULL)
- return -1;
- if (PyDict_SetItemString(dict, meth->ml_name, descr) < 0)
- return -1;
- Py_DECREF(descr);
- }
- return 0;
-}
-
-static int
-add_members(PyTypeObject *type, PyMemberDef *memb)
-{
- PyObject *dict = type->tp_dict;
-
- for (; memb->name != NULL; memb++) {
- PyObject *descr;
- if (PyDict_GetItemString(dict, memb->name))
- continue;
- descr = PyDescr_NewMember(type, memb);
- if (descr == NULL)
- return -1;
- if (PyDict_SetItemString(dict, memb->name, descr) < 0)
- return -1;
- Py_DECREF(descr);
- }
- return 0;
-}
-
-static int
-add_getset(PyTypeObject *type, PyGetSetDef *gsp)
-{
- PyObject *dict = type->tp_dict;
-
- for (; gsp->name != NULL; gsp++) {
- PyObject *descr;
- if (PyDict_GetItemString(dict, gsp->name))
- continue;
- descr = PyDescr_NewGetSet(type, gsp);
-
- if (descr == NULL)
- return -1;
- if (PyDict_SetItemString(dict, gsp->name, descr) < 0)
- return -1;
- Py_DECREF(descr);
- }
- return 0;
-}
-
-static void
-inherit_special(PyTypeObject *type, PyTypeObject *base)
-{
- Py_ssize_t oldsize, newsize;
-
- /* Special flag magic */
- if (!type->tp_as_buffer && base->tp_as_buffer) {
- type->tp_flags &= ~Py_TPFLAGS_HAVE_GETCHARBUFFER;
- type->tp_flags |=
- base->tp_flags & Py_TPFLAGS_HAVE_GETCHARBUFFER;
- }
- if (!type->tp_as_sequence && base->tp_as_sequence) {
- type->tp_flags &= ~Py_TPFLAGS_HAVE_SEQUENCE_IN;
- type->tp_flags |= base->tp_flags & Py_TPFLAGS_HAVE_SEQUENCE_IN;
- }
- if ((type->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS) !=
- (base->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS)) {
- if ((!type->tp_as_number && base->tp_as_number) ||
- (!type->tp_as_sequence && base->tp_as_sequence)) {
- type->tp_flags &= ~Py_TPFLAGS_HAVE_INPLACEOPS;
- if (!type->tp_as_number && !type->tp_as_sequence) {
- type->tp_flags |= base->tp_flags &
- Py_TPFLAGS_HAVE_INPLACEOPS;
- }
- }
- /* Wow */
- }
- if (!type->tp_as_number && base->tp_as_number) {
- type->tp_flags &= ~Py_TPFLAGS_CHECKTYPES;
- type->tp_flags |= base->tp_flags & Py_TPFLAGS_CHECKTYPES;
- }
-
- /* Copying basicsize is connected to the GC flags */
- oldsize = base->tp_basicsize;
- newsize = type->tp_basicsize ? type->tp_basicsize : oldsize;
- if (!(type->tp_flags & Py_TPFLAGS_HAVE_GC) &&
- (base->tp_flags & Py_TPFLAGS_HAVE_GC) &&
- (type->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE/*GC slots exist*/) &&
- (!type->tp_traverse && !type->tp_clear)) {
- type->tp_flags |= Py_TPFLAGS_HAVE_GC;
- if (type->tp_traverse == NULL)
- type->tp_traverse = base->tp_traverse;
- if (type->tp_clear == NULL)
- type->tp_clear = base->tp_clear;
- }
- if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
- /* The condition below could use some explanation.
- It appears that tp_new is not inherited for static types
- whose base class is 'object'; this seems to be a precaution
- so that old extension types don't suddenly become
- callable (object.__new__ wouldn't insure the invariants
- that the extension type's own factory function ensures).
- Heap types, of course, are under our control, so they do
- inherit tp_new; static extension types that specify some
- other built-in type as the default are considered
- new-style-aware so they also inherit object.__new__. */
- if (base != &PyBaseObject_Type ||
- (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
- if (type->tp_new == NULL)
- type->tp_new = base->tp_new;
- }
- }
- type->tp_basicsize = newsize;
-
- /* Copy other non-function slots */
-
-#undef COPYVAL
-#define COPYVAL(SLOT) \
- if (type->SLOT == 0) type->SLOT = base->SLOT
-
- COPYVAL(tp_itemsize);
- if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS) {
- COPYVAL(tp_weaklistoffset);
- }
- if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
- COPYVAL(tp_dictoffset);
- }
-}
-
-static void
-inherit_slots(PyTypeObject *type, PyTypeObject *base)
-{
- PyTypeObject *basebase;
-
-#undef SLOTDEFINED
-#undef COPYSLOT
-#undef COPYNUM
-#undef COPYSEQ
-#undef COPYMAP
-#undef COPYBUF
-
-#define SLOTDEFINED(SLOT) \
- (base->SLOT != 0 && \
- (basebase == NULL || base->SLOT != basebase->SLOT))
-
-#define COPYSLOT(SLOT) \
- if (!type->SLOT && SLOTDEFINED(SLOT)) type->SLOT = base->SLOT
-
-#define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT)
-#define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT)
-#define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT)
-#define COPYBUF(SLOT) COPYSLOT(tp_as_buffer->SLOT)
-
- /* This won't inherit indirect slots (from tp_as_number etc.)
- if type doesn't provide the space. */
-
- if (type->tp_as_number != NULL && base->tp_as_number != NULL) {
- basebase = base->tp_base;
- if (basebase->tp_as_number == NULL)
- basebase = NULL;
- COPYNUM(nb_add);
- COPYNUM(nb_subtract);
- COPYNUM(nb_multiply);
- COPYNUM(nb_divide);
- COPYNUM(nb_remainder);
- COPYNUM(nb_divmod);
- COPYNUM(nb_power);
- COPYNUM(nb_negative);
- COPYNUM(nb_positive);
- COPYNUM(nb_absolute);
- COPYNUM(nb_nonzero);
- COPYNUM(nb_invert);
- COPYNUM(nb_lshift);
- COPYNUM(nb_rshift);
- COPYNUM(nb_and);
- COPYNUM(nb_xor);
- COPYNUM(nb_or);
- COPYNUM(nb_coerce);
- COPYNUM(nb_int);
- COPYNUM(nb_long);
- COPYNUM(nb_float);
- COPYNUM(nb_oct);
- COPYNUM(nb_hex);
- COPYNUM(nb_inplace_add);
- COPYNUM(nb_inplace_subtract);
- COPYNUM(nb_inplace_multiply);
- COPYNUM(nb_inplace_divide);
- COPYNUM(nb_inplace_remainder);
- COPYNUM(nb_inplace_power);
- COPYNUM(nb_inplace_lshift);
- COPYNUM(nb_inplace_rshift);
- COPYNUM(nb_inplace_and);
- COPYNUM(nb_inplace_xor);
- COPYNUM(nb_inplace_or);
- if (base->tp_flags & Py_TPFLAGS_CHECKTYPES) {
- COPYNUM(nb_true_divide);
- COPYNUM(nb_floor_divide);
- COPYNUM(nb_inplace_true_divide);
- COPYNUM(nb_inplace_floor_divide);
- }
- if (base->tp_flags & Py_TPFLAGS_HAVE_INDEX) {
- COPYNUM(nb_index);
- }
- }
-
- if (type->tp_as_sequence != NULL && base->tp_as_sequence != NULL) {
- basebase = base->tp_base;
- if (basebase->tp_as_sequence == NULL)
- basebase = NULL;
- COPYSEQ(sq_length);
- COPYSEQ(sq_concat);
- COPYSEQ(sq_repeat);
- COPYSEQ(sq_item);
- COPYSEQ(sq_slice);
- COPYSEQ(sq_ass_item);
- COPYSEQ(sq_ass_slice);
- COPYSEQ(sq_contains);
- COPYSEQ(sq_inplace_concat);
- COPYSEQ(sq_inplace_repeat);
- }
-
- if (type->tp_as_mapping != NULL && base->tp_as_mapping != NULL) {
- basebase = base->tp_base;
- if (basebase->tp_as_mapping == NULL)
- basebase = NULL;
- COPYMAP(mp_length);
- COPYMAP(mp_subscript);
- COPYMAP(mp_ass_subscript);
- }
-
- if (type->tp_as_buffer != NULL && base->tp_as_buffer != NULL) {
- basebase = base->tp_base;
- if (basebase->tp_as_buffer == NULL)
- basebase = NULL;
- COPYBUF(bf_getreadbuffer);
- COPYBUF(bf_getwritebuffer);
- COPYBUF(bf_getsegcount);
- COPYBUF(bf_getcharbuffer);
- }
-
- basebase = base->tp_base;
-
- COPYSLOT(tp_dealloc);
- COPYSLOT(tp_print);
- if (type->tp_getattr == NULL && type->tp_getattro == NULL) {
- type->tp_getattr = base->tp_getattr;
- type->tp_getattro = base->tp_getattro;
- }
- if (type->tp_setattr == NULL && type->tp_setattro == NULL) {
- type->tp_setattr = base->tp_setattr;
- type->tp_setattro = base->tp_setattro;
- }
- /* tp_compare see tp_richcompare */
- COPYSLOT(tp_repr);
- /* tp_hash see tp_richcompare */
- COPYSLOT(tp_call);
- COPYSLOT(tp_str);
- if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) {
- if (type->tp_compare == NULL &&
- type->tp_richcompare == NULL &&
- type->tp_hash == NULL)
- {
- type->tp_compare = base->tp_compare;
- type->tp_richcompare = base->tp_richcompare;
- type->tp_hash = base->tp_hash;
- }
- }
- else {
- COPYSLOT(tp_compare);
- }
- if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_ITER) {
- COPYSLOT(tp_iter);
- COPYSLOT(tp_iternext);
- }
- if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
- COPYSLOT(tp_descr_get);
- COPYSLOT(tp_descr_set);
- COPYSLOT(tp_dictoffset);
- COPYSLOT(tp_init);
- COPYSLOT(tp_alloc);
- COPYSLOT(tp_is_gc);
- if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) ==
- (base->tp_flags & Py_TPFLAGS_HAVE_GC)) {
- /* They agree about gc. */
- COPYSLOT(tp_free);
- }
- else if ((type->tp_flags & Py_TPFLAGS_HAVE_GC) &&
- type->tp_free == NULL &&
- base->tp_free == _PyObject_Del) {
- /* A bit of magic to plug in the correct default
- * tp_free function when a derived class adds gc,
- * didn't define tp_free, and the base uses the
- * default non-gc tp_free.
- */
- type->tp_free = PyObject_GC_Del;
- }
- /* else they didn't agree about gc, and there isn't something
- * obvious to be done -- the type is on its own.
- */
- }
-}
-
-static int add_operators(PyTypeObject *);
-
-int
-PyType_Ready(PyTypeObject *type)
-{
- PyObject *dict, *bases;
- PyTypeObject *base;
- Py_ssize_t i, n;
-
- if (type->tp_flags & Py_TPFLAGS_READY) {
- assert(type->tp_dict != NULL);
- return 0;
- }
- assert((type->tp_flags & Py_TPFLAGS_READYING) == 0);
-
- type->tp_flags |= Py_TPFLAGS_READYING;
-
-#ifdef Py_TRACE_REFS
- /* PyType_Ready is the closest thing we have to a choke point
- * for type objects, so is the best place I can think of to try
- * to get type objects into the doubly-linked list of all objects.
- * Still, not all type objects go thru PyType_Ready.
- */
- _Py_AddToAllObjects((PyObject *)type, 0);
-#endif
-
- /* Initialize tp_base (defaults to BaseObject unless that's us) */
- base = type->tp_base;
- if (base == NULL && type != &PyBaseObject_Type) {
- base = type->tp_base = &PyBaseObject_Type;
- Py_INCREF(base);
- }
-
- /* Now the only way base can still be NULL is if type is
- * &PyBaseObject_Type.
- */
-
- /* Initialize the base class */
- if (base && base->tp_dict == NULL) {
- if (PyType_Ready(base) < 0)
- goto error;
- }
-
- /* Initialize ob_type if NULL. This means extensions that want to be
- compilable separately on Windows can call PyType_Ready() instead of
- initializing the ob_type field of their type objects. */
- /* The test for base != NULL is really unnecessary, since base is only
- NULL when type is &PyBaseObject_Type, and we know its ob_type is
- not NULL (it's initialized to &PyType_Type). But coverity doesn't
- know that. */
- if (type->ob_type == NULL && base != NULL)
- type->ob_type = base->ob_type;
-
- /* Initialize tp_bases */
- bases = type->tp_bases;
- if (bases == NULL) {
- if (base == NULL)
- bases = PyTuple_New(0);
- else
- bases = PyTuple_Pack(1, base);
- if (bases == NULL)
- goto error;
- type->tp_bases = bases;
- }
-
- /* Initialize tp_dict */
- dict = type->tp_dict;
- if (dict == NULL) {
- dict = PyDict_New();
- if (dict == NULL)
- goto error;
- type->tp_dict = dict;
- }
-
- /* Add type-specific descriptors to tp_dict */
- if (add_operators(type) < 0)
- goto error;
- if (type->tp_methods != NULL) {
- if (add_methods(type, type->tp_methods) < 0)
- goto error;
- }
- if (type->tp_members != NULL) {
- if (add_members(type, type->tp_members) < 0)
- goto error;
- }
- if (type->tp_getset != NULL) {
- if (add_getset(type, type->tp_getset) < 0)
- goto error;
- }
-
- /* Calculate method resolution order */
- if (mro_internal(type) < 0) {
- goto error;
- }
-
- /* Inherit special flags from dominant base */
- if (type->tp_base != NULL)
- inherit_special(type, type->tp_base);
-
- /* Initialize tp_dict properly */
- bases = type->tp_mro;
- assert(bases != NULL);
- assert(PyTuple_Check(bases));
- n = PyTuple_GET_SIZE(bases);
- for (i = 1; i < n; i++) {
- PyObject *b = PyTuple_GET_ITEM(bases, i);
- if (PyType_Check(b))
- inherit_slots(type, (PyTypeObject *)b);
- }
-
- /* Sanity check for tp_free. */
- if (PyType_IS_GC(type) && (type->tp_flags & Py_TPFLAGS_BASETYPE) &&
- (type->tp_free == NULL || type->tp_free == PyObject_Del)) {
- /* This base class needs to call tp_free, but doesn't have
- * one, or its tp_free is for non-gc'ed objects.
- */
- PyErr_Format(PyExc_TypeError, "type '%.100s' participates in "
- "gc and is a base type but has inappropriate "
- "tp_free slot",
- type->tp_name);
- goto error;
- }
-
- /* if the type dictionary doesn't contain a __doc__, set it from
- the tp_doc slot.
- */
- if (PyDict_GetItemString(type->tp_dict, "__doc__") == NULL) {
- if (type->tp_doc != NULL) {
- PyObject *doc = PyString_FromString(type->tp_doc);
- if (doc == NULL)
- goto error;
- PyDict_SetItemString(type->tp_dict, "__doc__", doc);
- Py_DECREF(doc);
- } else {
- PyDict_SetItemString(type->tp_dict,
- "__doc__", Py_None);
- }
- }
-
- /* Some more special stuff */
- base = type->tp_base;
- if (base != NULL) {
- if (type->tp_as_number == NULL)
- type->tp_as_number = base->tp_as_number;
- if (type->tp_as_sequence == NULL)
- type->tp_as_sequence = base->tp_as_sequence;
- if (type->tp_as_mapping == NULL)
- type->tp_as_mapping = base->tp_as_mapping;
- if (type->tp_as_buffer == NULL)
- type->tp_as_buffer = base->tp_as_buffer;
- }
-
- /* Link into each base class's list of subclasses */
- bases = type->tp_bases;
- n = PyTuple_GET_SIZE(bases);
- for (i = 0; i < n; i++) {
- PyObject *b = PyTuple_GET_ITEM(bases, i);
- if (PyType_Check(b) &&
- add_subclass((PyTypeObject *)b, type) < 0)
- goto error;
- }
-
- /* All done -- set the ready flag */
- assert(type->tp_dict != NULL);
- type->tp_flags =
- (type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;
- return 0;
-
- error:
- type->tp_flags &= ~Py_TPFLAGS_READYING;
- return -1;
-}
-
-static int
-add_subclass(PyTypeObject *base, PyTypeObject *type)
-{
- Py_ssize_t i;
- int result;
- PyObject *list, *ref, *newobj;
-
- list = base->tp_subclasses;
- if (list == NULL) {
- base->tp_subclasses = list = PyList_New(0);
- if (list == NULL)
- return -1;
- }
- assert(PyList_Check(list));
- newobj = PyWeakref_NewRef((PyObject *)type, NULL);
- i = PyList_GET_SIZE(list);
- while (--i >= 0) {
- ref = PyList_GET_ITEM(list, i);
- assert(PyWeakref_CheckRef(ref));
- if (PyWeakref_GET_OBJECT(ref) == Py_None)
- return PyList_SetItem(list, i, newobj);
- }
- result = PyList_Append(list, newobj);
- Py_DECREF(newobj);
- return result;
-}
-
-static void
-remove_subclass(PyTypeObject *base, PyTypeObject *type)
-{
- Py_ssize_t i;
- PyObject *list, *ref;
-
- list = base->tp_subclasses;
- if (list == NULL) {
- return;
- }
- assert(PyList_Check(list));
- i = PyList_GET_SIZE(list);
- while (--i >= 0) {
- ref = PyList_GET_ITEM(list, i);
- assert(PyWeakref_CheckRef(ref));
- if (PyWeakref_GET_OBJECT(ref) == (PyObject*)type) {
- /* this can't fail, right? */
- PySequence_DelItem(list, i);
- return;
- }
- }
-}
-
-static int
-check_num_args(PyObject *ob, int n)
-{
- if (!PyTuple_CheckExact(ob)) {
- PyErr_SetString(PyExc_SystemError,
- "PyArg_UnpackTuple() argument list is not a tuple");
- return 0;
- }
- if (n == PyTuple_GET_SIZE(ob))
- return 1;
- PyErr_Format(
- PyExc_TypeError,
- "expected %d arguments, got %zd", n, PyTuple_GET_SIZE(ob));
- return 0;
-}
-
-/* Generic wrappers for overloadable 'operators' such as __getitem__ */
-
-/* There's a wrapper *function* for each distinct function typedef used
- for type object slots (e.g. binaryfunc, ternaryfunc, etc.). There's a
- wrapper *table* for each distinct operation (e.g. __len__, __add__).
- Most tables have only one entry; the tables for binary operators have two
- entries, one regular and one with reversed arguments. */
-
-static PyObject *
-wrap_lenfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- lenfunc func = (lenfunc)wrapped;
- Py_ssize_t res;
-
- if (!check_num_args(args, 0))
- return NULL;
- res = (*func)(self);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- return PyInt_FromLong((long)res);
-}
-
-static PyObject *
-wrap_inquirypred(PyObject *self, PyObject *args, void *wrapped)
-{
- inquiry func = (inquiry)wrapped;
- int res;
-
- if (!check_num_args(args, 0))
- return NULL;
- res = (*func)(self);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- return PyBool_FromLong((long)res);
-}
-
-static PyObject *
-wrap_binaryfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- binaryfunc func = (binaryfunc)wrapped;
- PyObject *other;
-
- if (!check_num_args(args, 1))
- return NULL;
- other = PyTuple_GET_ITEM(args, 0);
- return (*func)(self, other);
-}
-
-static PyObject *
-wrap_binaryfunc_l(PyObject *self, PyObject *args, void *wrapped)
-{
- binaryfunc func = (binaryfunc)wrapped;
- PyObject *other;
-
- if (!check_num_args(args, 1))
- return NULL;
- other = PyTuple_GET_ITEM(args, 0);
- if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
- !PyType_IsSubtype(other->ob_type, self->ob_type)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return (*func)(self, other);
-}
-
-static PyObject *
-wrap_binaryfunc_r(PyObject *self, PyObject *args, void *wrapped)
-{
- binaryfunc func = (binaryfunc)wrapped;
- PyObject *other;
-
- if (!check_num_args(args, 1))
- return NULL;
- other = PyTuple_GET_ITEM(args, 0);
- if (!(self->ob_type->tp_flags & Py_TPFLAGS_CHECKTYPES) &&
- !PyType_IsSubtype(other->ob_type, self->ob_type)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return (*func)(other, self);
-}
-
-static PyObject *
-wrap_coercefunc(PyObject *self, PyObject *args, void *wrapped)
-{
- coercion func = (coercion)wrapped;
- PyObject *other, *res;
- int ok;
-
- if (!check_num_args(args, 1))
- return NULL;
- other = PyTuple_GET_ITEM(args, 0);
- ok = func(&self, &other);
- if (ok < 0)
- return NULL;
- if (ok > 0) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- res = PyTuple_New(2);
- if (res == NULL) {
- Py_DECREF(self);
- Py_DECREF(other);
- return NULL;
- }
- PyTuple_SET_ITEM(res, 0, self);
- PyTuple_SET_ITEM(res, 1, other);
- return res;
-}
-
-static PyObject *
-wrap_ternaryfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- ternaryfunc func = (ternaryfunc)wrapped;
- PyObject *other;
- PyObject *third = Py_None;
-
- /* Note: This wrapper only works for __pow__() */
-
- if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third))
- return NULL;
- return (*func)(self, other, third);
-}
-
-static PyObject *
-wrap_ternaryfunc_r(PyObject *self, PyObject *args, void *wrapped)
-{
- ternaryfunc func = (ternaryfunc)wrapped;
- PyObject *other;
- PyObject *third = Py_None;
-
- /* Note: This wrapper only works for __pow__() */
-
- if (!PyArg_UnpackTuple(args, "", 1, 2, &other, &third))
- return NULL;
- return (*func)(other, self, third);
-}
-
-static PyObject *
-wrap_unaryfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- unaryfunc func = (unaryfunc)wrapped;
-
- if (!check_num_args(args, 0))
- return NULL;
- return (*func)(self);
-}
-
-static PyObject *
-wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- ssizeargfunc func = (ssizeargfunc)wrapped;
- PyObject* o;
- Py_ssize_t i;
-
- if (!PyArg_UnpackTuple(args, "", 1, 1, &o))
- return NULL;
- i = PyNumber_AsSsize_t(o, PyExc_OverflowError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- return (*func)(self, i);
-}
-
-static Py_ssize_t
-getindex(PyObject *self, PyObject *arg)
-{
- Py_ssize_t i;
-
- i = PyNumber_AsSsize_t(arg, PyExc_OverflowError);
- if (i == -1 && PyErr_Occurred())
- return -1;
- if (i < 0) {
- PySequenceMethods *sq = self->ob_type->tp_as_sequence;
- if (sq && sq->sq_length) {
- Py_ssize_t n = (*sq->sq_length)(self);
- if (n < 0)
- return -1;
- i += n;
- }
- }
- return i;
-}
-
-static PyObject *
-wrap_sq_item(PyObject *self, PyObject *args, void *wrapped)
-{
- ssizeargfunc func = (ssizeargfunc)wrapped;
- PyObject *arg;
- Py_ssize_t i;
-
- if (PyTuple_GET_SIZE(args) == 1) {
- arg = PyTuple_GET_ITEM(args, 0);
- i = getindex(self, arg);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- return (*func)(self, i);
- }
- check_num_args(args, 1);
- assert(PyErr_Occurred());
- return NULL;
-}
-
-static PyObject *
-wrap_ssizessizeargfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- ssizessizeargfunc func = (ssizessizeargfunc)wrapped;
- Py_ssize_t i, j;
-
- if (!PyArg_ParseTuple(args, "nn", &i, &j))
- return NULL;
- return (*func)(self, i, j);
-}
-
-static PyObject *
-wrap_sq_setitem(PyObject *self, PyObject *args, void *wrapped)
-{
- ssizeobjargproc func = (ssizeobjargproc)wrapped;
- Py_ssize_t i;
- int res;
- PyObject *arg, *value;
-
- if (!PyArg_UnpackTuple(args, "", 2, 2, &arg, &value))
- return NULL;
- i = getindex(self, arg);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- res = (*func)(self, i, value);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_sq_delitem(PyObject *self, PyObject *args, void *wrapped)
-{
- ssizeobjargproc func = (ssizeobjargproc)wrapped;
- Py_ssize_t i;
- int res;
- PyObject *arg;
-
- if (!check_num_args(args, 1))
- return NULL;
- arg = PyTuple_GET_ITEM(args, 0);
- i = getindex(self, arg);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- res = (*func)(self, i, NULL);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_ssizessizeobjargproc(PyObject *self, PyObject *args, void *wrapped)
-{
- ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;
- Py_ssize_t i, j;
- int res;
- PyObject *value;
-
- if (!PyArg_ParseTuple(args, "nnO", &i, &j, &value))
- return NULL;
- res = (*func)(self, i, j, value);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_delslice(PyObject *self, PyObject *args, void *wrapped)
-{
- ssizessizeobjargproc func = (ssizessizeobjargproc)wrapped;
- Py_ssize_t i, j;
- int res;
-
- if (!PyArg_ParseTuple(args, "nn", &i, &j))
- return NULL;
- res = (*func)(self, i, j, NULL);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-/* XXX objobjproc is a misnomer; should be objargpred */
-static PyObject *
-wrap_objobjproc(PyObject *self, PyObject *args, void *wrapped)
-{
- objobjproc func = (objobjproc)wrapped;
- int res;
- PyObject *value;
-
- if (!check_num_args(args, 1))
- return NULL;
- value = PyTuple_GET_ITEM(args, 0);
- res = (*func)(self, value);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- else
- return PyBool_FromLong(res);
-}
-
-static PyObject *
-wrap_objobjargproc(PyObject *self, PyObject *args, void *wrapped)
-{
- objobjargproc func = (objobjargproc)wrapped;
- int res;
- PyObject *key, *value;
-
- if (!PyArg_UnpackTuple(args, "", 2, 2, &key, &value))
- return NULL;
- res = (*func)(self, key, value);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_delitem(PyObject *self, PyObject *args, void *wrapped)
-{
- objobjargproc func = (objobjargproc)wrapped;
- int res;
- PyObject *key;
-
- if (!check_num_args(args, 1))
- return NULL;
- key = PyTuple_GET_ITEM(args, 0);
- res = (*func)(self, key, NULL);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_cmpfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- cmpfunc func = (cmpfunc)wrapped;
- int res;
- PyObject *other;
-
- if (!check_num_args(args, 1))
- return NULL;
- other = PyTuple_GET_ITEM(args, 0);
- if (other->ob_type->tp_compare != func &&
- !PyType_IsSubtype(other->ob_type, self->ob_type)) {
- PyErr_Format(
- PyExc_TypeError,
- "%s.__cmp__(x,y) requires y to be a '%s', not a '%s'",
- self->ob_type->tp_name,
- self->ob_type->tp_name,
- other->ob_type->tp_name);
- return NULL;
- }
- res = (*func)(self, other);
- if (PyErr_Occurred())
- return NULL;
- return PyInt_FromLong((long)res);
-}
-
-/* Helper to check for object.__setattr__ or __delattr__ applied to a type.
- This is called the Carlo Verre hack after its discoverer. */
-static int
-hackcheck(PyObject *self, setattrofunc func, char *what)
-{
- PyTypeObject *type = self->ob_type;
- while (type && type->tp_flags & Py_TPFLAGS_HEAPTYPE)
- type = type->tp_base;
- /* If type is NULL now, this is a really weird type.
- In the same of backwards compatibility (?), just shut up. */
- if (type && type->tp_setattro != func) {
- PyErr_Format(PyExc_TypeError,
- "can't apply this %s to %s object",
- what,
- type->tp_name);
- return 0;
- }
- return 1;
-}
-
-static PyObject *
-wrap_setattr(PyObject *self, PyObject *args, void *wrapped)
-{
- setattrofunc func = (setattrofunc)wrapped;
- int res;
- PyObject *name, *value;
-
- if (!PyArg_UnpackTuple(args, "", 2, 2, &name, &value))
- return NULL;
- if (!hackcheck(self, func, "__setattr__"))
- return NULL;
- res = (*func)(self, name, value);
- if (res < 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_delattr(PyObject *self, PyObject *args, void *wrapped)
-{
- setattrofunc func = (setattrofunc)wrapped;
- int res;
- PyObject *name;
-
- if (!check_num_args(args, 1))
- return NULL;
- name = PyTuple_GET_ITEM(args, 0);
- if (!hackcheck(self, func, "__delattr__"))
- return NULL;
- res = (*func)(self, name, NULL);
- if (res < 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_hashfunc(PyObject *self, PyObject *args, void *wrapped)
-{
- hashfunc func = (hashfunc)wrapped;
- long res;
-
- if (!check_num_args(args, 0))
- return NULL;
- res = (*func)(self);
- if (res == -1 && PyErr_Occurred())
- return NULL;
- return PyInt_FromLong(res);
-}
-
-static PyObject *
-wrap_call(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds)
-{
- ternaryfunc func = (ternaryfunc)wrapped;
-
- return (*func)(self, args, kwds);
-}
-
-static PyObject *
-wrap_richcmpfunc(PyObject *self, PyObject *args, void *wrapped, int op)
-{
- richcmpfunc func = (richcmpfunc)wrapped;
- PyObject *other;
-
- if (!check_num_args(args, 1))
- return NULL;
- other = PyTuple_GET_ITEM(args, 0);
- return (*func)(self, other, op);
-}
-
-#undef RICHCMP_WRAPPER
-#define RICHCMP_WRAPPER(NAME, OP) \
-static PyObject * \
-richcmp_##NAME(PyObject *self, PyObject *args, void *wrapped) \
-{ \
- return wrap_richcmpfunc(self, args, wrapped, OP); \
-}
-
-RICHCMP_WRAPPER(lt, Py_LT)
-RICHCMP_WRAPPER(le, Py_LE)
-RICHCMP_WRAPPER(eq, Py_EQ)
-RICHCMP_WRAPPER(ne, Py_NE)
-RICHCMP_WRAPPER(gt, Py_GT)
-RICHCMP_WRAPPER(ge, Py_GE)
-
-static PyObject *
-wrap_next(PyObject *self, PyObject *args, void *wrapped)
-{
- unaryfunc func = (unaryfunc)wrapped;
- PyObject *res;
-
- if (!check_num_args(args, 0))
- return NULL;
- res = (*func)(self);
- if (res == NULL && !PyErr_Occurred())
- PyErr_SetNone(PyExc_StopIteration);
- return res;
-}
-
-static PyObject *
-wrap_descr_get(PyObject *self, PyObject *args, void *wrapped)
-{
- descrgetfunc func = (descrgetfunc)wrapped;
- PyObject *obj;
- PyObject *type = NULL;
-
- if (!PyArg_UnpackTuple(args, "", 1, 2, &obj, &type))
- return NULL;
- if (obj == Py_None)
- obj = NULL;
- if (type == Py_None)
- type = NULL;
- if (type == NULL &&obj == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "__get__(None, None) is invalid");
- return NULL;
- }
- return (*func)(self, obj, type);
-}
-
-static PyObject *
-wrap_descr_set(PyObject *self, PyObject *args, void *wrapped)
-{
- descrsetfunc func = (descrsetfunc)wrapped;
- PyObject *obj, *value;
- int ret;
-
- if (!PyArg_UnpackTuple(args, "", 2, 2, &obj, &value))
- return NULL;
- ret = (*func)(self, obj, value);
- if (ret < 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_descr_delete(PyObject *self, PyObject *args, void *wrapped)
-{
- descrsetfunc func = (descrsetfunc)wrapped;
- PyObject *obj;
- int ret;
-
- if (!check_num_args(args, 1))
- return NULL;
- obj = PyTuple_GET_ITEM(args, 0);
- ret = (*func)(self, obj, NULL);
- if (ret < 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-wrap_init(PyObject *self, PyObject *args, void *wrapped, PyObject *kwds)
-{
- initproc func = (initproc)wrapped;
-
- if (func(self, args, kwds) < 0)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyObject *
-tp_new_wrapper(PyObject *self, PyObject *args, PyObject *kwds)
-{
- PyTypeObject *type, *subtype, *staticbase;
- PyObject *arg0, *res;
-
- if (self == NULL || !PyType_Check(self))
- Py_FatalError("__new__() called with non-type 'self'");
- type = (PyTypeObject *)self;
- if (!PyTuple_Check(args) || PyTuple_GET_SIZE(args) < 1) {
- PyErr_Format(PyExc_TypeError,
- "%s.__new__(): not enough arguments",
- type->tp_name);
- return NULL;
- }
- arg0 = PyTuple_GET_ITEM(args, 0);
- if (!PyType_Check(arg0)) {
- PyErr_Format(PyExc_TypeError,
- "%s.__new__(X): X is not a type object (%s)",
- type->tp_name,
- arg0->ob_type->tp_name);
- return NULL;
- }
- subtype = (PyTypeObject *)arg0;
- if (!PyType_IsSubtype(subtype, type)) {
- PyErr_Format(PyExc_TypeError,
- "%s.__new__(%s): %s is not a subtype of %s",
- type->tp_name,
- subtype->tp_name,
- subtype->tp_name,
- type->tp_name);
- return NULL;
- }
-
- /* Check that the use doesn't do something silly and unsafe like
- object.__new__(dict). To do this, we check that the
- most derived base that's not a heap type is this type. */
- staticbase = subtype;
- while (staticbase && (staticbase->tp_flags & Py_TPFLAGS_HEAPTYPE))
- staticbase = staticbase->tp_base;
- /* If staticbase is NULL now, it is a really weird type.
- In the same of backwards compatibility (?), just shut up. */
- if (staticbase && staticbase->tp_new != type->tp_new) {
- PyErr_Format(PyExc_TypeError,
- "%s.__new__(%s) is not safe, use %s.__new__()",
- type->tp_name,
- subtype->tp_name,
- staticbase == NULL ? "?" : staticbase->tp_name);
- return NULL;
- }
-
- args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
- if (args == NULL)
- return NULL;
- res = type->tp_new(subtype, args, kwds);
- Py_DECREF(args);
- return res;
-}
-
-static struct PyMethodDef tp_new_methoddef[] = {
- {"__new__", (PyCFunction)tp_new_wrapper, METH_KEYWORDS,
- PyDoc_STR("T.__new__(S, ...) -> "
- "a new object with type S, a subtype of T")},
- {0}
-};
-
-static int
-add_tp_new_wrapper(PyTypeObject *type)
-{
- PyObject *func;
-
- if (PyDict_GetItemString(type->tp_dict, "__new__") != NULL)
- return 0;
- func = PyCFunction_New(tp_new_methoddef, (PyObject *)type);
- if (func == NULL)
- return -1;
- if (PyDict_SetItemString(type->tp_dict, "__new__", func)) {
- Py_DECREF(func);
- return -1;
- }
- Py_DECREF(func);
- return 0;
-}
-
-/* Slot wrappers that call the corresponding __foo__ slot. See comments
- below at override_slots() for more explanation. */
-
-#define SLOT0(FUNCNAME, OPSTR) \
-static PyObject * \
-FUNCNAME(PyObject *self) \
-{ \
- static PyObject *cache_str; \
- return call_method(self, OPSTR, &cache_str, "()"); \
-}
-
-#define SLOT1(FUNCNAME, OPSTR, ARG1TYPE, ARGCODES) \
-static PyObject * \
-FUNCNAME(PyObject *self, ARG1TYPE arg1) \
-{ \
- static PyObject *cache_str; \
- return call_method(self, OPSTR, &cache_str, "(" ARGCODES ")", arg1); \
-}
-
-/* Boolean helper for SLOT1BINFULL().
- right.__class__ is a nontrivial subclass of left.__class__. */
-static int
-method_is_overloaded(PyObject *left, PyObject *right, char *name)
-{
- PyObject *a, *b;
- int ok;
-
- b = PyObject_GetAttrString((PyObject *)(right->ob_type), name);
- if (b == NULL) {
- PyErr_Clear();
- /* If right doesn't have it, it's not overloaded */
- return 0;
- }
-
- a = PyObject_GetAttrString((PyObject *)(left->ob_type), name);
- if (a == NULL) {
- PyErr_Clear();
- Py_DECREF(b);
- /* If right has it but left doesn't, it's overloaded */
- return 1;
- }
-
- ok = PyObject_RichCompareBool(a, b, Py_NE);
- Py_DECREF(a);
- Py_DECREF(b);
- if (ok < 0) {
- PyErr_Clear();
- return 0;
- }
-
- return ok;
-}
-
-
-#define SLOT1BINFULL(FUNCNAME, TESTFUNC, SLOTNAME, OPSTR, ROPSTR) \
-static PyObject * \
-FUNCNAME(PyObject *self, PyObject *other) \
-{ \
- static PyObject *cache_str, *rcache_str; \
- int do_other = self->ob_type != other->ob_type && \
- other->ob_type->tp_as_number != NULL && \
- other->ob_type->tp_as_number->SLOTNAME == TESTFUNC; \
- if (self->ob_type->tp_as_number != NULL && \
- self->ob_type->tp_as_number->SLOTNAME == TESTFUNC) { \
- PyObject *r; \
- if (do_other && \
- PyType_IsSubtype(other->ob_type, self->ob_type) && \
- method_is_overloaded(self, other, ROPSTR)) { \
- r = call_maybe( \
- other, ROPSTR, &rcache_str, "(O)", self); \
- if (r != Py_NotImplemented) \
- return r; \
- Py_DECREF(r); \
- do_other = 0; \
- } \
- r = call_maybe( \
- self, OPSTR, &cache_str, "(O)", other); \
- if (r != Py_NotImplemented || \
- other->ob_type == self->ob_type) \
- return r; \
- Py_DECREF(r); \
- } \
- if (do_other) { \
- return call_maybe( \
- other, ROPSTR, &rcache_str, "(O)", self); \
- } \
- Py_INCREF(Py_NotImplemented); \
- return Py_NotImplemented; \
-}
-
-#define SLOT1BIN(FUNCNAME, SLOTNAME, OPSTR, ROPSTR) \
- SLOT1BINFULL(FUNCNAME, FUNCNAME, SLOTNAME, OPSTR, ROPSTR)
-
-#define SLOT2(FUNCNAME, OPSTR, ARG1TYPE, ARG2TYPE, ARGCODES) \
-static PyObject * \
-FUNCNAME(PyObject *self, ARG1TYPE arg1, ARG2TYPE arg2) \
-{ \
- static PyObject *cache_str; \
- return call_method(self, OPSTR, &cache_str, \
- "(" ARGCODES ")", arg1, arg2); \
-}
-
-static Py_ssize_t
-slot_sq_length(PyObject *self)
-{
- static PyObject *len_str;
- PyObject *res = call_method(self, "__len__", &len_str, "()");
- Py_ssize_t len;
-
- if (res == NULL)
- return -1;
- len = PyInt_AsSsize_t(res);
- Py_DECREF(res);
- if (len < 0) {
- if (!PyErr_Occurred())
- PyErr_SetString(PyExc_ValueError,
- "__len__() should return >= 0");
- return -1;
- }
- return len;
-}
-
-/* Super-optimized version of slot_sq_item.
- Other slots could do the same... */
-static PyObject *
-slot_sq_item(PyObject *self, Py_ssize_t i)
-{
- static PyObject *getitem_str;
- PyObject *func, *args = NULL, *ival = NULL, *retval = NULL;
- descrgetfunc f;
-
- if (getitem_str == NULL) {
- getitem_str = PyString_InternFromString("__getitem__");
- if (getitem_str == NULL)
- return NULL;
- }
- func = _PyType_Lookup(self->ob_type, getitem_str);
- if (func != NULL) {
- if ((f = func->ob_type->tp_descr_get) == NULL)
- Py_INCREF(func);
- else {
- func = f(func, self, (PyObject *)(self->ob_type));
- if (func == NULL) {
- return NULL;
- }
- }
- ival = PyInt_FromSsize_t(i);
- if (ival != NULL) {
- args = PyTuple_New(1);
- if (args != NULL) {
- PyTuple_SET_ITEM(args, 0, ival);
- retval = PyObject_Call(func, args, NULL);
- Py_XDECREF(args);
- Py_XDECREF(func);
- return retval;
- }
- }
- }
- else {
- PyErr_SetObject(PyExc_AttributeError, getitem_str);
- }
- Py_XDECREF(args);
- Py_XDECREF(ival);
- Py_XDECREF(func);
- return NULL;
-}
-
-SLOT2(slot_sq_slice, "__getslice__", Py_ssize_t, Py_ssize_t, "nn")
-
-static int
-slot_sq_ass_item(PyObject *self, Py_ssize_t index, PyObject *value)
-{
- PyObject *res;
- static PyObject *delitem_str, *setitem_str;
-
- if (value == NULL)
- res = call_method(self, "__delitem__", &delitem_str,
- "(n)", index);
- else
- res = call_method(self, "__setitem__", &setitem_str,
- "(nO)", index, value);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static int
-slot_sq_ass_slice(PyObject *self, Py_ssize_t i, Py_ssize_t j, PyObject *value)
-{
- PyObject *res;
- static PyObject *delslice_str, *setslice_str;
-
- if (value == NULL)
- res = call_method(self, "__delslice__", &delslice_str,
- "(nn)", i, j);
- else
- res = call_method(self, "__setslice__", &setslice_str,
- "(nnO)", i, j, value);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static int
-slot_sq_contains(PyObject *self, PyObject *value)
-{
- PyObject *func, *res, *args;
- int result = -1;
-
- static PyObject *contains_str;
-
- func = lookup_maybe(self, "__contains__", &contains_str);
- if (func != NULL) {
- args = PyTuple_Pack(1, value);
- if (args == NULL)
- res = NULL;
- else {
- res = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- }
- Py_DECREF(func);
- if (res != NULL) {
- result = PyObject_IsTrue(res);
- Py_DECREF(res);
- }
- }
- else if (! PyErr_Occurred()) {
- /* Possible results: -1 and 1 */
- result = (int)_PySequence_IterSearch(self, value,
- PY_ITERSEARCH_CONTAINS);
- }
- return result;
-}
-
-#define slot_mp_length slot_sq_length
-
-SLOT1(slot_mp_subscript, "__getitem__", PyObject *, "O")
-
-static int
-slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
-{
- PyObject *res;
- static PyObject *delitem_str, *setitem_str;
-
- if (value == NULL)
- res = call_method(self, "__delitem__", &delitem_str,
- "(O)", key);
- else
- res = call_method(self, "__setitem__", &setitem_str,
- "(OO)", key, value);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-SLOT1BIN(slot_nb_add, nb_add, "__add__", "__radd__")
-SLOT1BIN(slot_nb_subtract, nb_subtract, "__sub__", "__rsub__")
-SLOT1BIN(slot_nb_multiply, nb_multiply, "__mul__", "__rmul__")
-SLOT1BIN(slot_nb_divide, nb_divide, "__div__", "__rdiv__")
-SLOT1BIN(slot_nb_remainder, nb_remainder, "__mod__", "__rmod__")
-SLOT1BIN(slot_nb_divmod, nb_divmod, "__divmod__", "__rdivmod__")
-
-static PyObject *slot_nb_power(PyObject *, PyObject *, PyObject *);
-
-SLOT1BINFULL(slot_nb_power_binary, slot_nb_power,
- nb_power, "__pow__", "__rpow__")
-
-static PyObject *
-slot_nb_power(PyObject *self, PyObject *other, PyObject *modulus)
-{
- static PyObject *pow_str;
-
- if (modulus == Py_None)
- return slot_nb_power_binary(self, other);
- /* Three-arg power doesn't use __rpow__. But ternary_op
- can call this when the second argument's type uses
- slot_nb_power, so check before calling self.__pow__. */
- if (self->ob_type->tp_as_number != NULL &&
- self->ob_type->tp_as_number->nb_power == slot_nb_power) {
- return call_method(self, "__pow__", &pow_str,
- "(OO)", other, modulus);
- }
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-SLOT0(slot_nb_negative, "__neg__")
-SLOT0(slot_nb_positive, "__pos__")
-SLOT0(slot_nb_absolute, "__abs__")
-
-static int
-slot_nb_nonzero(PyObject *self)
-{
- PyObject *func, *args;
- static PyObject *nonzero_str, *len_str;
- int result = -1;
-
- func = lookup_maybe(self, "__nonzero__", &nonzero_str);
- if (func == NULL) {
- if (PyErr_Occurred())
- return -1;
- func = lookup_maybe(self, "__len__", &len_str);
- if (func == NULL)
- return PyErr_Occurred() ? -1 : 1;
- }
- args = PyTuple_New(0);
- if (args != NULL) {
- PyObject *temp = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- if (temp != NULL) {
- if (PyInt_CheckExact(temp) || PyBool_Check(temp))
- result = PyObject_IsTrue(temp);
- else {
- PyErr_Format(PyExc_TypeError,
- "__nonzero__ should return "
- "bool or int, returned %s",
- temp->ob_type->tp_name);
- result = -1;
- }
- Py_DECREF(temp);
- }
- }
- Py_DECREF(func);
- return result;
-}
-
-
-static PyObject *
-slot_nb_index(PyObject *self)
-{
- static PyObject *index_str;
- return call_method(self, "__index__", &index_str, "()");
-}
-
-
-SLOT0(slot_nb_invert, "__invert__")
-SLOT1BIN(slot_nb_lshift, nb_lshift, "__lshift__", "__rlshift__")
-SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__")
-SLOT1BIN(slot_nb_and, nb_and, "__and__", "__rand__")
-SLOT1BIN(slot_nb_xor, nb_xor, "__xor__", "__rxor__")
-SLOT1BIN(slot_nb_or, nb_or, "__or__", "__ror__")
-
-static int
-slot_nb_coerce(PyObject **a, PyObject **b)
-{
- static PyObject *coerce_str;
- PyObject *self = *a, *other = *b;
-
- if (self->ob_type->tp_as_number != NULL &&
- self->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
- PyObject *r;
- r = call_maybe(
- self, "__coerce__", &coerce_str, "(O)", other);
- if (r == NULL)
- return -1;
- if (r == Py_NotImplemented) {
- Py_DECREF(r);
- }
- else {
- if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
- PyErr_SetString(PyExc_TypeError,
- "__coerce__ didn't return a 2-tuple");
- Py_DECREF(r);
- return -1;
- }
- *a = PyTuple_GET_ITEM(r, 0);
- Py_INCREF(*a);
- *b = PyTuple_GET_ITEM(r, 1);
- Py_INCREF(*b);
- Py_DECREF(r);
- return 0;
- }
- }
- if (other->ob_type->tp_as_number != NULL &&
- other->ob_type->tp_as_number->nb_coerce == slot_nb_coerce) {
- PyObject *r;
- r = call_maybe(
- other, "__coerce__", &coerce_str, "(O)", self);
- if (r == NULL)
- return -1;
- if (r == Py_NotImplemented) {
- Py_DECREF(r);
- return 1;
- }
- if (!PyTuple_Check(r) || PyTuple_GET_SIZE(r) != 2) {
- PyErr_SetString(PyExc_TypeError,
- "__coerce__ didn't return a 2-tuple");
- Py_DECREF(r);
- return -1;
- }
- *a = PyTuple_GET_ITEM(r, 1);
- Py_INCREF(*a);
- *b = PyTuple_GET_ITEM(r, 0);
- Py_INCREF(*b);
- Py_DECREF(r);
- return 0;
- }
- return 1;
-}
-
-SLOT0(slot_nb_int, "__int__")
-SLOT0(slot_nb_long, "__long__")
-SLOT0(slot_nb_float, "__float__")
-SLOT0(slot_nb_oct, "__oct__")
-SLOT0(slot_nb_hex, "__hex__")
-SLOT1(slot_nb_inplace_add, "__iadd__", PyObject *, "O")
-SLOT1(slot_nb_inplace_subtract, "__isub__", PyObject *, "O")
-SLOT1(slot_nb_inplace_multiply, "__imul__", PyObject *, "O")
-SLOT1(slot_nb_inplace_divide, "__idiv__", PyObject *, "O")
-SLOT1(slot_nb_inplace_remainder, "__imod__", PyObject *, "O")
-/* Can't use SLOT1 here, because nb_inplace_power is ternary */
-static PyObject *
-slot_nb_inplace_power(PyObject *self, PyObject * arg1, PyObject *arg2)
-{
- static PyObject *cache_str;
- return call_method(self, "__ipow__", &cache_str, "(" "O" ")", arg1);
-}
-SLOT1(slot_nb_inplace_lshift, "__ilshift__", PyObject *, "O")
-SLOT1(slot_nb_inplace_rshift, "__irshift__", PyObject *, "O")
-SLOT1(slot_nb_inplace_and, "__iand__", PyObject *, "O")
-SLOT1(slot_nb_inplace_xor, "__ixor__", PyObject *, "O")
-SLOT1(slot_nb_inplace_or, "__ior__", PyObject *, "O")
-SLOT1BIN(slot_nb_floor_divide, nb_floor_divide,
- "__floordiv__", "__rfloordiv__")
-SLOT1BIN(slot_nb_true_divide, nb_true_divide, "__truediv__", "__rtruediv__")
-SLOT1(slot_nb_inplace_floor_divide, "__ifloordiv__", PyObject *, "O")
-SLOT1(slot_nb_inplace_true_divide, "__itruediv__", PyObject *, "O")
-
-static int
-half_compare(PyObject *self, PyObject *other)
-{
- PyObject *func, *args, *res;
- static PyObject *cmp_str;
- Py_ssize_t c;
-
- func = lookup_method(self, "__cmp__", &cmp_str);
- if (func == NULL) {
- PyErr_Clear();
- }
- else {
- args = PyTuple_Pack(1, other);
- if (args == NULL)
- res = NULL;
- else {
- res = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- }
- Py_DECREF(func);
- if (res != Py_NotImplemented) {
- if (res == NULL)
- return -2;
- c = PyInt_AsLong(res);
- Py_DECREF(res);
- if (c == -1 && PyErr_Occurred())
- return -2;
- return (c < 0) ? -1 : (c > 0) ? 1 : 0;
- }
- Py_DECREF(res);
- }
- return 2;
-}
-
-/* This slot is published for the benefit of try_3way_compare in object.c */
-int
-_PyObject_SlotCompare(PyObject *self, PyObject *other)
-{
- int c;
-
- if (self->ob_type->tp_compare == _PyObject_SlotCompare) {
- c = half_compare(self, other);
- if (c <= 1)
- return c;
- }
- if (other->ob_type->tp_compare == _PyObject_SlotCompare) {
- c = half_compare(other, self);
- if (c < -1)
- return -2;
- if (c <= 1)
- return -c;
- }
- return (void *)self < (void *)other ? -1 :
- (void *)self > (void *)other ? 1 : 0;
-}
-
-static PyObject *
-slot_tp_repr(PyObject *self)
-{
- PyObject *func, *res;
- static PyObject *repr_str;
-
- func = lookup_method(self, "__repr__", &repr_str);
- if (func != NULL) {
- res = PyEval_CallObject(func, NULL);
- Py_DECREF(func);
- return res;
- }
- PyErr_Clear();
- return PyString_FromFormat("<%s object at %p>",
- self->ob_type->tp_name, self);
-}
-
-static PyObject *
-slot_tp_str(PyObject *self)
-{
- PyObject *func, *res;
- static PyObject *str_str;
-
- func = lookup_method(self, "__str__", &str_str);
- if (func != NULL) {
- res = PyEval_CallObject(func, NULL);
- Py_DECREF(func);
- return res;
- }
- else {
- PyErr_Clear();
- return slot_tp_repr(self);
- }
-}
-
-static long
-slot_tp_hash(PyObject *self)
-{
- PyObject *func;
- static PyObject *hash_str, *eq_str, *cmp_str;
- long h;
-
- func = lookup_method(self, "__hash__", &hash_str);
-
- if (func != NULL) {
- PyObject *res = PyEval_CallObject(func, NULL);
- Py_DECREF(func);
- if (res == NULL)
- return -1;
- if (PyLong_Check(res))
- h = PyLong_Type.tp_hash(res);
- else
- h = PyInt_AsLong(res);
- Py_DECREF(res);
- }
- else {
- PyErr_Clear();
- func = lookup_method(self, "__eq__", &eq_str);
- if (func == NULL) {
- PyErr_Clear();
- func = lookup_method(self, "__cmp__", &cmp_str);
- }
- if (func != NULL) {
- PyErr_Format(PyExc_TypeError, "unhashable type: '%.200s'",
- self->ob_type->tp_name);
- Py_DECREF(func);
- return -1;
- }
- PyErr_Clear();
- h = _Py_HashPointer((void *)self);
- }
- if (h == -1 && !PyErr_Occurred())
- h = -2;
- return h;
-}
-
-static PyObject *
-slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds)
-{
- static PyObject *call_str;
- PyObject *meth = lookup_method(self, "__call__", &call_str);
- PyObject *res;
-
- if (meth == NULL)
- return NULL;
-
- /* PyObject_Call() will end up calling slot_tp_call() again if
- the object returned for __call__ has __call__ itself defined
- upon it. This can be an infinite recursion if you set
- __call__ in a class to an instance of it. */
- if (Py_EnterRecursiveCall(" in __call__")) {
- Py_DECREF(meth);
- return NULL;
- }
- res = PyObject_Call(meth, args, kwds);
- Py_LeaveRecursiveCall();
-
- Py_DECREF(meth);
- return res;
-}
-
-/* There are two slot dispatch functions for tp_getattro.
-
- - slot_tp_getattro() is used when __getattribute__ is overridden
- but no __getattr__ hook is present;
-
- - slot_tp_getattr_hook() is used when a __getattr__ hook is present.
-
- The code in update_one_slot() always installs slot_tp_getattr_hook(); this
- detects the absence of __getattr__ and then installs the simpler slot if
- necessary. */
-
-static PyObject *
-slot_tp_getattro(PyObject *self, PyObject *name)
-{
- static PyObject *getattribute_str = NULL;
- return call_method(self, "__getattribute__", &getattribute_str,
- "(O)", name);
-}
-
-static PyObject *
-slot_tp_getattr_hook(PyObject *self, PyObject *name)
-{
- PyTypeObject *tp = self->ob_type;
- PyObject *getattr, *getattribute, *res;
- static PyObject *getattribute_str = NULL;
- static PyObject *getattr_str = NULL;
-
- if (getattr_str == NULL) {
- getattr_str = PyString_InternFromString("__getattr__");
- if (getattr_str == NULL)
- return NULL;
- }
- if (getattribute_str == NULL) {
- getattribute_str =
- PyString_InternFromString("__getattribute__");
- if (getattribute_str == NULL)
- return NULL;
- }
- getattr = _PyType_Lookup(tp, getattr_str);
- if (getattr == NULL) {
- /* No __getattr__ hook: use a simpler dispatcher */
- tp->tp_getattro = slot_tp_getattro;
- return slot_tp_getattro(self, name);
- }
- getattribute = _PyType_Lookup(tp, getattribute_str);
- if (getattribute == NULL ||
- (getattribute->ob_type == &PyWrapperDescr_Type &&
- ((PyWrapperDescrObject *)getattribute)->d_wrapped ==
- (void *)PyObject_GenericGetAttr))
- res = PyObject_GenericGetAttr(self, name);
- else
- res = PyObject_CallFunctionObjArgs(getattribute, self, name, NULL);
- if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyErr_Clear();
- res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL);
- }
- return res;
-}
-
-static int
-slot_tp_setattro(PyObject *self, PyObject *name, PyObject *value)
-{
- PyObject *res;
- static PyObject *delattr_str, *setattr_str;
-
- if (value == NULL)
- res = call_method(self, "__delattr__", &delattr_str,
- "(O)", name);
- else
- res = call_method(self, "__setattr__", &setattr_str,
- "(OO)", name, value);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-/* Map rich comparison operators to their __xx__ namesakes */
-static char *name_op[] = {
- "__lt__",
- "__le__",
- "__eq__",
- "__ne__",
- "__gt__",
- "__ge__",
-};
-
-static PyObject *
-half_richcompare(PyObject *self, PyObject *other, int op)
-{
- PyObject *func, *args, *res;
- static PyObject *op_str[6];
-
- func = lookup_method(self, name_op[op], &op_str[op]);
- if (func == NULL) {
- PyErr_Clear();
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- args = PyTuple_Pack(1, other);
- if (args == NULL)
- res = NULL;
- else {
- res = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- }
- Py_DECREF(func);
- return res;
-}
-
-static PyObject *
-slot_tp_richcompare(PyObject *self, PyObject *other, int op)
-{
- PyObject *res;
-
- if (self->ob_type->tp_richcompare == slot_tp_richcompare) {
- res = half_richcompare(self, other, op);
- if (res != Py_NotImplemented)
- return res;
- Py_DECREF(res);
- }
- if (other->ob_type->tp_richcompare == slot_tp_richcompare) {
- res = half_richcompare(other, self, _Py_SwappedOp[op]);
- if (res != Py_NotImplemented) {
- return res;
- }
- Py_DECREF(res);
- }
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
-}
-
-static PyObject *
-slot_tp_iter(PyObject *self)
-{
- PyObject *func, *res;
- static PyObject *iter_str, *getitem_str;
-
- func = lookup_method(self, "__iter__", &iter_str);
- if (func != NULL) {
- PyObject *args;
- args = res = PyTuple_New(0);
- if (args != NULL) {
- res = PyObject_Call(func, args, NULL);
- Py_DECREF(args);
- }
- Py_DECREF(func);
- return res;
- }
- PyErr_Clear();
- func = lookup_method(self, "__getitem__", &getitem_str);
- if (func == NULL) {
- PyErr_Format(PyExc_TypeError,
- "'%.200s' object is not iterable",
- self->ob_type->tp_name);
- return NULL;
- }
- Py_DECREF(func);
- return PySeqIter_New(self);
-}
-
-static PyObject *
-slot_tp_iternext(PyObject *self)
-{
- static PyObject *next_str;
- return call_method(self, "next", &next_str, "()");
-}
-
-static PyObject *
-slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type)
-{
- PyTypeObject *tp = self->ob_type;
- PyObject *get;
- static PyObject *get_str = NULL;
-
- if (get_str == NULL) {
- get_str = PyString_InternFromString("__get__");
- if (get_str == NULL)
- return NULL;
- }
- get = _PyType_Lookup(tp, get_str);
- if (get == NULL) {
- /* Avoid further slowdowns */
- if (tp->tp_descr_get == slot_tp_descr_get)
- tp->tp_descr_get = NULL;
- Py_INCREF(self);
- return self;
- }
- if (obj == NULL)
- obj = Py_None;
- if (type == NULL)
- type = Py_None;
- return PyObject_CallFunctionObjArgs(get, self, obj, type, NULL);
-}
-
-static int
-slot_tp_descr_set(PyObject *self, PyObject *target, PyObject *value)
-{
- PyObject *res;
- static PyObject *del_str, *set_str;
-
- if (value == NULL)
- res = call_method(self, "__delete__", &del_str,
- "(O)", target);
- else
- res = call_method(self, "__set__", &set_str,
- "(OO)", target, value);
- if (res == NULL)
- return -1;
- Py_DECREF(res);
- return 0;
-}
-
-static int
-slot_tp_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- static PyObject *init_str;
- PyObject *meth = lookup_method(self, "__init__", &init_str);
- PyObject *res;
-
- if (meth == NULL)
- return -1;
- res = PyObject_Call(meth, args, kwds);
- Py_DECREF(meth);
- if (res == NULL)
- return -1;
- if (res != Py_None) {
- PyErr_Format(PyExc_TypeError,
- "__init__() should return None, not '%.200s'",
- res->ob_type->tp_name);
- Py_DECREF(res);
- return -1;
- }
- Py_DECREF(res);
- return 0;
-}
-
-static PyObject *
-slot_tp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- static PyObject *new_str;
- PyObject *func;
- PyObject *newargs, *x;
- Py_ssize_t i, n;
-
- if (new_str == NULL) {
- new_str = PyString_InternFromString("__new__");
- if (new_str == NULL)
- return NULL;
- }
- func = PyObject_GetAttr((PyObject *)type, new_str);
- if (func == NULL)
- return NULL;
- assert(PyTuple_Check(args));
- n = PyTuple_GET_SIZE(args);
- newargs = PyTuple_New(n+1);
- if (newargs == NULL)
- return NULL;
- Py_INCREF(type);
- PyTuple_SET_ITEM(newargs, 0, (PyObject *)type);
- for (i = 0; i < n; i++) {
- x = PyTuple_GET_ITEM(args, i);
- Py_INCREF(x);
- PyTuple_SET_ITEM(newargs, i+1, x);
- }
- x = PyObject_Call(func, newargs, kwds);
- Py_DECREF(newargs);
- Py_DECREF(func);
- return x;
-}
-
-static void
-slot_tp_del(PyObject *self)
-{
- static PyObject *del_str = NULL;
- PyObject *del, *res;
- PyObject *error_type, *error_value, *error_traceback;
-
- /* Temporarily resurrect the object. */
- assert(self->ob_refcnt == 0);
- self->ob_refcnt = 1;
-
- /* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- /* Execute __del__ method, if any. */
- del = lookup_maybe(self, "__del__", &del_str);
- if (del != NULL) {
- res = PyEval_CallObject(del, NULL);
- if (res == NULL)
- PyErr_WriteUnraisable(del);
- else
- Py_DECREF(res);
- Py_DECREF(del);
- }
-
- /* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
-
- /* Undo the temporary resurrection; can't use DECREF here, it would
- * cause a recursive call.
- */
- assert(self->ob_refcnt > 0);
- if (--self->ob_refcnt == 0)
- return; /* this is the normal path out */
-
- /* __del__ resurrected it! Make it look like the original Py_DECREF
- * never happened.
- */
- {
- Py_ssize_t refcnt = self->ob_refcnt;
- _Py_NewReference(self);
- self->ob_refcnt = refcnt;
- }
- assert(!PyType_IS_GC(self->ob_type) ||
- _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
- /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
- * we need to undo that. */
- _Py_DEC_REFTOTAL;
- /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
- * chain, so no more to do there.
- * If COUNT_ALLOCS, the original decref bumped tp_frees, and
- * _Py_NewReference bumped tp_allocs: both of those need to be
- * undone.
- */
-#ifdef COUNT_ALLOCS
- --self->ob_type->tp_frees;
- --self->ob_type->tp_allocs;
-#endif
-}
-
-
-/* Table mapping __foo__ names to tp_foo offsets and slot_tp_foo wrapper
- functions. The offsets here are relative to the 'PyHeapTypeObject'
- structure, which incorporates the additional structures used for numbers,
- sequences and mappings.
- Note that multiple names may map to the same slot (e.g. __eq__,
- __ne__ etc. all map to tp_richcompare) and one name may map to multiple
- slots (e.g. __str__ affects tp_str as well as tp_repr). The table is
- terminated with an all-zero entry. (This table is further initialized and
- sorted in init_slotdefs() below.) */
-
-typedef struct wrapperbase slotdef;
-
-#undef TPSLOT
-#undef FLSLOT
-#undef ETSLOT
-#undef SQSLOT
-#undef MPSLOT
-#undef NBSLOT
-#undef UNSLOT
-#undef IBSLOT
-#undef BINSLOT
-#undef RBINSLOT
-
-#define TPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
- {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
- PyDoc_STR(DOC)}
-#define FLSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC, FLAGS) \
- {NAME, offsetof(PyTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
- PyDoc_STR(DOC), FLAGS}
-#define ETSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
- {NAME, offsetof(PyHeapTypeObject, SLOT), (void *)(FUNCTION), WRAPPER, \
- PyDoc_STR(DOC)}
-#define SQSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
- ETSLOT(NAME, as_sequence.SLOT, FUNCTION, WRAPPER, DOC)
-#define MPSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
- ETSLOT(NAME, as_mapping.SLOT, FUNCTION, WRAPPER, DOC)
-#define NBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
- ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, DOC)
-#define UNSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
- ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \
- "x." NAME "() <==> " DOC)
-#define IBSLOT(NAME, SLOT, FUNCTION, WRAPPER, DOC) \
- ETSLOT(NAME, as_number.SLOT, FUNCTION, WRAPPER, \
- "x." NAME "(y) <==> x" DOC "y")
-#define BINSLOT(NAME, SLOT, FUNCTION, DOC) \
- ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \
- "x." NAME "(y) <==> x" DOC "y")
-#define RBINSLOT(NAME, SLOT, FUNCTION, DOC) \
- ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \
- "x." NAME "(y) <==> y" DOC "x")
-#define BINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
- ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_l, \
- "x." NAME "(y) <==> " DOC)
-#define RBINSLOTNOTINFIX(NAME, SLOT, FUNCTION, DOC) \
- ETSLOT(NAME, as_number.SLOT, FUNCTION, wrap_binaryfunc_r, \
- "x." NAME "(y) <==> " DOC)
-
-static slotdef slotdefs[] = {
- SQSLOT("__len__", sq_length, slot_sq_length, wrap_lenfunc,
- "x.__len__() <==> len(x)"),
- /* Heap types defining __add__/__mul__ have sq_concat/sq_repeat == NULL.
- The logic in abstract.c always falls back to nb_add/nb_multiply in
- this case. Defining both the nb_* and the sq_* slots to call the
- user-defined methods has unexpected side-effects, as shown by
- test_descr.notimplemented() */
- SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc,
- "x.__add__(y) <==> x+y"),
- SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc,
- "x.__mul__(n) <==> x*n"),
- SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc,
- "x.__rmul__(n) <==> n*x"),
- SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item,
- "x.__getitem__(y) <==> x[y]"),
- SQSLOT("__getslice__", sq_slice, slot_sq_slice, wrap_ssizessizeargfunc,
- "x.__getslice__(i, j) <==> x[i:j]\n\
- \n\
- Use of negative indices is not supported."),
- SQSLOT("__setitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_setitem,
- "x.__setitem__(i, y) <==> x[i]=y"),
- SQSLOT("__delitem__", sq_ass_item, slot_sq_ass_item, wrap_sq_delitem,
- "x.__delitem__(y) <==> del x[y]"),
- SQSLOT("__setslice__", sq_ass_slice, slot_sq_ass_slice,
- wrap_ssizessizeobjargproc,
- "x.__setslice__(i, j, y) <==> x[i:j]=y\n\
- \n\
- Use of negative indices is not supported."),
- SQSLOT("__delslice__", sq_ass_slice, slot_sq_ass_slice, wrap_delslice,
- "x.__delslice__(i, j) <==> del x[i:j]\n\
- \n\
- Use of negative indices is not supported."),
- SQSLOT("__contains__", sq_contains, slot_sq_contains, wrap_objobjproc,
- "x.__contains__(y) <==> y in x"),
- SQSLOT("__iadd__", sq_inplace_concat, NULL,
- wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"),
- SQSLOT("__imul__", sq_inplace_repeat, NULL,
- wrap_indexargfunc, "x.__imul__(y) <==> x*=y"),
-
- MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc,
- "x.__len__() <==> len(x)"),
- MPSLOT("__getitem__", mp_subscript, slot_mp_subscript,
- wrap_binaryfunc,
- "x.__getitem__(y) <==> x[y]"),
- MPSLOT("__setitem__", mp_ass_subscript, slot_mp_ass_subscript,
- wrap_objobjargproc,
- "x.__setitem__(i, y) <==> x[i]=y"),
- MPSLOT("__delitem__", mp_ass_subscript, slot_mp_ass_subscript,
- wrap_delitem,
- "x.__delitem__(y) <==> del x[y]"),
-
- BINSLOT("__add__", nb_add, slot_nb_add,
- "+"),
- RBINSLOT("__radd__", nb_add, slot_nb_add,
- "+"),
- BINSLOT("__sub__", nb_subtract, slot_nb_subtract,
- "-"),
- RBINSLOT("__rsub__", nb_subtract, slot_nb_subtract,
- "-"),
- BINSLOT("__mul__", nb_multiply, slot_nb_multiply,
- "*"),
- RBINSLOT("__rmul__", nb_multiply, slot_nb_multiply,
- "*"),
- BINSLOT("__div__", nb_divide, slot_nb_divide,
- "/"),
- RBINSLOT("__rdiv__", nb_divide, slot_nb_divide,
- "/"),
- BINSLOT("__mod__", nb_remainder, slot_nb_remainder,
- "%"),
- RBINSLOT("__rmod__", nb_remainder, slot_nb_remainder,
- "%"),
- BINSLOTNOTINFIX("__divmod__", nb_divmod, slot_nb_divmod,
- "divmod(x, y)"),
- RBINSLOTNOTINFIX("__rdivmod__", nb_divmod, slot_nb_divmod,
- "divmod(y, x)"),
- NBSLOT("__pow__", nb_power, slot_nb_power, wrap_ternaryfunc,
- "x.__pow__(y[, z]) <==> pow(x, y[, z])"),
- NBSLOT("__rpow__", nb_power, slot_nb_power, wrap_ternaryfunc_r,
- "y.__rpow__(x[, z]) <==> pow(x, y[, z])"),
- UNSLOT("__neg__", nb_negative, slot_nb_negative, wrap_unaryfunc, "-x"),
- UNSLOT("__pos__", nb_positive, slot_nb_positive, wrap_unaryfunc, "+x"),
- UNSLOT("__abs__", nb_absolute, slot_nb_absolute, wrap_unaryfunc,
- "abs(x)"),
- UNSLOT("__nonzero__", nb_nonzero, slot_nb_nonzero, wrap_inquirypred,
- "x != 0"),
- UNSLOT("__invert__", nb_invert, slot_nb_invert, wrap_unaryfunc, "~x"),
- BINSLOT("__lshift__", nb_lshift, slot_nb_lshift, "<<"),
- RBINSLOT("__rlshift__", nb_lshift, slot_nb_lshift, "<<"),
- BINSLOT("__rshift__", nb_rshift, slot_nb_rshift, ">>"),
- RBINSLOT("__rrshift__", nb_rshift, slot_nb_rshift, ">>"),
- BINSLOT("__and__", nb_and, slot_nb_and, "&"),
- RBINSLOT("__rand__", nb_and, slot_nb_and, "&"),
- BINSLOT("__xor__", nb_xor, slot_nb_xor, "^"),
- RBINSLOT("__rxor__", nb_xor, slot_nb_xor, "^"),
- BINSLOT("__or__", nb_or, slot_nb_or, "|"),
- RBINSLOT("__ror__", nb_or, slot_nb_or, "|"),
- NBSLOT("__coerce__", nb_coerce, slot_nb_coerce, wrap_coercefunc,
- "x.__coerce__(y) <==> coerce(x, y)"),
- UNSLOT("__int__", nb_int, slot_nb_int, wrap_unaryfunc,
- "int(x)"),
- UNSLOT("__long__", nb_long, slot_nb_long, wrap_unaryfunc,
- "long(x)"),
- UNSLOT("__float__", nb_float, slot_nb_float, wrap_unaryfunc,
- "float(x)"),
- UNSLOT("__oct__", nb_oct, slot_nb_oct, wrap_unaryfunc,
- "oct(x)"),
- UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
- "hex(x)"),
- NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,
- "x[y:z] <==> x[y.__index__():z.__index__()]"),
- IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
- wrap_binaryfunc, "+"),
- IBSLOT("__isub__", nb_inplace_subtract, slot_nb_inplace_subtract,
- wrap_binaryfunc, "-"),
- IBSLOT("__imul__", nb_inplace_multiply, slot_nb_inplace_multiply,
- wrap_binaryfunc, "*"),
- IBSLOT("__idiv__", nb_inplace_divide, slot_nb_inplace_divide,
- wrap_binaryfunc, "/"),
- IBSLOT("__imod__", nb_inplace_remainder, slot_nb_inplace_remainder,
- wrap_binaryfunc, "%"),
- IBSLOT("__ipow__", nb_inplace_power, slot_nb_inplace_power,
- wrap_binaryfunc, "**"),
- IBSLOT("__ilshift__", nb_inplace_lshift, slot_nb_inplace_lshift,
- wrap_binaryfunc, "<<"),
- IBSLOT("__irshift__", nb_inplace_rshift, slot_nb_inplace_rshift,
- wrap_binaryfunc, ">>"),
- IBSLOT("__iand__", nb_inplace_and, slot_nb_inplace_and,
- wrap_binaryfunc, "&"),
- IBSLOT("__ixor__", nb_inplace_xor, slot_nb_inplace_xor,
- wrap_binaryfunc, "^"),
- IBSLOT("__ior__", nb_inplace_or, slot_nb_inplace_or,
- wrap_binaryfunc, "|"),
- BINSLOT("__floordiv__", nb_floor_divide, slot_nb_floor_divide, "//"),
- RBINSLOT("__rfloordiv__", nb_floor_divide, slot_nb_floor_divide, "//"),
- BINSLOT("__truediv__", nb_true_divide, slot_nb_true_divide, "/"),
- RBINSLOT("__rtruediv__", nb_true_divide, slot_nb_true_divide, "/"),
- IBSLOT("__ifloordiv__", nb_inplace_floor_divide,
- slot_nb_inplace_floor_divide, wrap_binaryfunc, "//"),
- IBSLOT("__itruediv__", nb_inplace_true_divide,
- slot_nb_inplace_true_divide, wrap_binaryfunc, "/"),
-
- TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc,
- "x.__str__() <==> str(x)"),
- TPSLOT("__str__", tp_print, NULL, NULL, ""),
- TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc,
- "x.__repr__() <==> repr(x)"),
- TPSLOT("__repr__", tp_print, NULL, NULL, ""),
- TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc,
- "x.__cmp__(y) <==> cmp(x,y)"),
- TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc,
- "x.__hash__() <==> hash(x)"),
- FLSLOT("__call__", tp_call, slot_tp_call, (wrapperfunc)wrap_call,
- "x.__call__(...) <==> x(...)", PyWrapperFlag_KEYWORDS),
- TPSLOT("__getattribute__", tp_getattro, slot_tp_getattr_hook,
- wrap_binaryfunc, "x.__getattribute__('name') <==> x.name"),
- TPSLOT("__getattribute__", tp_getattr, NULL, NULL, ""),
- TPSLOT("__getattr__", tp_getattro, slot_tp_getattr_hook, NULL, ""),
- TPSLOT("__getattr__", tp_getattr, NULL, NULL, ""),
- TPSLOT("__setattr__", tp_setattro, slot_tp_setattro, wrap_setattr,
- "x.__setattr__('name', value) <==> x.name = value"),
- TPSLOT("__setattr__", tp_setattr, NULL, NULL, ""),
- TPSLOT("__delattr__", tp_setattro, slot_tp_setattro, wrap_delattr,
- "x.__delattr__('name') <==> del x.name"),
- TPSLOT("__delattr__", tp_setattr, NULL, NULL, ""),
- TPSLOT("__lt__", tp_richcompare, slot_tp_richcompare, richcmp_lt,
- "x.__lt__(y) <==> x<y"),
- TPSLOT("__le__", tp_richcompare, slot_tp_richcompare, richcmp_le,
- "x.__le__(y) <==> x<=y"),
- TPSLOT("__eq__", tp_richcompare, slot_tp_richcompare, richcmp_eq,
- "x.__eq__(y) <==> x==y"),
- TPSLOT("__ne__", tp_richcompare, slot_tp_richcompare, richcmp_ne,
- "x.__ne__(y) <==> x!=y"),
- TPSLOT("__gt__", tp_richcompare, slot_tp_richcompare, richcmp_gt,
- "x.__gt__(y) <==> x>y"),
- TPSLOT("__ge__", tp_richcompare, slot_tp_richcompare, richcmp_ge,
- "x.__ge__(y) <==> x>=y"),
- TPSLOT("__iter__", tp_iter, slot_tp_iter, wrap_unaryfunc,
- "x.__iter__() <==> iter(x)"),
- TPSLOT("next", tp_iternext, slot_tp_iternext, wrap_next,
- "x.next() -> the next value, or raise StopIteration"),
- TPSLOT("__get__", tp_descr_get, slot_tp_descr_get, wrap_descr_get,
- "descr.__get__(obj[, type]) -> value"),
- TPSLOT("__set__", tp_descr_set, slot_tp_descr_set, wrap_descr_set,
- "descr.__set__(obj, value)"),
- TPSLOT("__delete__", tp_descr_set, slot_tp_descr_set,
- wrap_descr_delete, "descr.__delete__(obj)"),
- FLSLOT("__init__", tp_init, slot_tp_init, (wrapperfunc)wrap_init,
- "x.__init__(...) initializes x; "
- "see x.__class__.__doc__ for signature",
- PyWrapperFlag_KEYWORDS),
- TPSLOT("__new__", tp_new, slot_tp_new, NULL, ""),
- TPSLOT("__del__", tp_del, slot_tp_del, NULL, ""),
- {NULL}
-};
-
-/* Given a type pointer and an offset gotten from a slotdef entry, return a
- pointer to the actual slot. This is not quite the same as simply adding
- the offset to the type pointer, since it takes care to indirect through the
- proper indirection pointer (as_buffer, etc.); it returns NULL if the
- indirection pointer is NULL. */
-static void **
-slotptr(PyTypeObject *type, int ioffset)
-{
- char *ptr;
- long offset = ioffset;
-
- /* Note: this depends on the order of the members of PyHeapTypeObject! */
- assert(offset >= 0);
- assert((size_t)offset < offsetof(PyHeapTypeObject, as_buffer));
- if ((size_t)offset >= offsetof(PyHeapTypeObject, as_sequence)) {
- ptr = (char *)type->tp_as_sequence;
- offset -= offsetof(PyHeapTypeObject, as_sequence);
- }
- else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_mapping)) {
- ptr = (char *)type->tp_as_mapping;
- offset -= offsetof(PyHeapTypeObject, as_mapping);
- }
- else if ((size_t)offset >= offsetof(PyHeapTypeObject, as_number)) {
- ptr = (char *)type->tp_as_number;
- offset -= offsetof(PyHeapTypeObject, as_number);
- }
- else {
- ptr = (char *)type;
- }
- if (ptr != NULL)
- ptr += offset;
- return (void **)ptr;
-}
-
-/* Length of array of slotdef pointers used to store slots with the
- same __name__. There should be at most MAX_EQUIV-1 slotdef entries with
- the same __name__, for any __name__. Since that's a static property, it is
- appropriate to declare fixed-size arrays for this. */
-#define MAX_EQUIV 10
-
-/* Return a slot pointer for a given name, but ONLY if the attribute has
- exactly one slot function. The name must be an interned string. */
-static void **
-resolve_slotdups(PyTypeObject *type, PyObject *name)
-{
- /* XXX Maybe this could be optimized more -- but is it worth it? */
-
- /* pname and ptrs act as a little cache */
- static PyObject *pname;
- static slotdef *ptrs[MAX_EQUIV];
- slotdef *p, **pp;
- void **res, **ptr;
-
- if (pname != name) {
- /* Collect all slotdefs that match name into ptrs. */
- pname = name;
- pp = ptrs;
- for (p = slotdefs; p->name_strobj; p++) {
- if (p->name_strobj == name)
- *pp++ = p;
- }
- *pp = NULL;
- }
-
- /* Look in all matching slots of the type; if exactly one of these has
- a filled-in slot, return its value. Otherwise return NULL. */
- res = NULL;
- for (pp = ptrs; *pp; pp++) {
- ptr = slotptr(type, (*pp)->offset);
- if (ptr == NULL || *ptr == NULL)
- continue;
- if (res != NULL)
- return NULL;
- res = ptr;
- }
- return res;
-}
-
-/* Common code for update_slots_callback() and fixup_slot_dispatchers(). This
- does some incredibly complex thinking and then sticks something into the
- slot. (It sees if the adjacent slotdefs for the same slot have conflicting
- interests, and then stores a generic wrapper or a specific function into
- the slot.) Return a pointer to the next slotdef with a different offset,
- because that's convenient for fixup_slot_dispatchers(). */
-static slotdef *
-update_one_slot(PyTypeObject *type, slotdef *p)
-{
- PyObject *descr;
- PyWrapperDescrObject *d;
- void *generic = NULL, *specific = NULL;
- int use_generic = 0;
- int offset = p->offset;
- void **ptr = slotptr(type, offset);
-
- if (ptr == NULL) {
- do {
- ++p;
- } while (p->offset == offset);
- return p;
- }
- do {
- descr = _PyType_Lookup(type, p->name_strobj);
- if (descr == NULL)
- continue;
- if (descr->ob_type == &PyWrapperDescr_Type) {
- void **tptr = resolve_slotdups(type, p->name_strobj);
- if (tptr == NULL || tptr == ptr)
- generic = p->function;
- d = (PyWrapperDescrObject *)descr;
- if (d->d_base->wrapper == p->wrapper &&
- PyType_IsSubtype(type, d->d_type))
- {
- if (specific == NULL ||
- specific == d->d_wrapped)
- specific = d->d_wrapped;
- else
- use_generic = 1;
- }
- }
- else if (descr->ob_type == &PyCFunction_Type &&
- PyCFunction_GET_FUNCTION(descr) ==
- (PyCFunction)tp_new_wrapper &&
- strcmp(p->name, "__new__") == 0)
- {
- /* The __new__ wrapper is not a wrapper descriptor,
- so must be special-cased differently.
- If we don't do this, creating an instance will
- always use slot_tp_new which will look up
- __new__ in the MRO which will call tp_new_wrapper
- which will look through the base classes looking
- for a static base and call its tp_new (usually
- PyType_GenericNew), after performing various
- sanity checks and constructing a new argument
- list. Cut all that nonsense short -- this speeds
- up instance creation tremendously. */
- specific = (void *)type->tp_new;
- /* XXX I'm not 100% sure that there isn't a hole
- in this reasoning that requires additional
- sanity checks. I'll buy the first person to
- point out a bug in this reasoning a beer. */
- }
- else {
- use_generic = 1;
- generic = p->function;
- }
- } while ((++p)->offset == offset);
- if (specific && !use_generic)
- *ptr = specific;
- else
- *ptr = generic;
- return p;
-}
-
-/* In the type, update the slots whose slotdefs are gathered in the pp array.
- This is a callback for update_subclasses(). */
-static int
-update_slots_callback(PyTypeObject *type, void *data)
-{
- slotdef **pp = (slotdef **)data;
-
- for (; *pp; pp++)
- update_one_slot(type, *pp);
- return 0;
-}
-
-/* Comparison function for qsort() to compare slotdefs by their offset, and
- for equal offset by their address (to force a stable sort). */
-static int
-slotdef_cmp(const void *aa, const void *bb)
-{
- const slotdef *a = (const slotdef *)aa, *b = (const slotdef *)bb;
- int c = a->offset - b->offset;
- if (c != 0)
- return c;
- else
- /* Cannot use a-b, as this gives off_t,
- which may lose precision when converted to int. */
- return (a > b) ? 1 : (a < b) ? -1 : 0;
-}
-
-/* Initialize the slotdefs table by adding interned string objects for the
- names and sorting the entries. */
-static void
-init_slotdefs(void)
-{
- slotdef *p;
- static int initialized = 0;
-
- if (initialized)
- return;
- for (p = slotdefs; p->name; p++) {
- p->name_strobj = PyString_InternFromString(p->name);
- if (!p->name_strobj)
- Py_FatalError("Out of memory interning slotdef names");
- }
- qsort((void *)slotdefs, (size_t)(p-slotdefs), sizeof(slotdef),
- slotdef_cmp);
- initialized = 1;
-}
-
-/* Update the slots after assignment to a class (type) attribute. */
-static int
-update_slot(PyTypeObject *type, PyObject *name)
-{
- slotdef *ptrs[MAX_EQUIV];
- slotdef *p;
- slotdef **pp;
- int offset;
-
- init_slotdefs();
- pp = ptrs;
- for (p = slotdefs; p->name; p++) {
- /* XXX assume name is interned! */
- if (p->name_strobj == name)
- *pp++ = p;
- }
- *pp = NULL;
- for (pp = ptrs; *pp; pp++) {
- p = *pp;
- offset = p->offset;
- while (p > slotdefs && (p-1)->offset == offset)
- --p;
- *pp = p;
- }
- if (ptrs[0] == NULL)
- return 0; /* Not an attribute that affects any slots */
- return update_subclasses(type, name,
- update_slots_callback, (void *)ptrs);
-}
-
-/* Store the proper functions in the slot dispatches at class (type)
- definition time, based upon which operations the class overrides in its
- dict. */
-static void
-fixup_slot_dispatchers(PyTypeObject *type)
-{
- slotdef *p;
-
- init_slotdefs();
- for (p = slotdefs; p->name; )
- p = update_one_slot(type, p);
-}
-
-static void
-update_all_slots(PyTypeObject* type)
-{
- slotdef *p;
-
- init_slotdefs();
- for (p = slotdefs; p->name; p++) {
- /* update_slot returns int but can't actually fail */
- update_slot(type, p->name_strobj);
- }
-}
-
-/* recurse_down_subclasses() and update_subclasses() are mutually
- recursive functions to call a callback for all subclasses,
- but refraining from recursing into subclasses that define 'name'. */
-
-static int
-update_subclasses(PyTypeObject *type, PyObject *name,
- update_callback callback, void *data)
-{
- if (callback(type, data) < 0)
- return -1;
- return recurse_down_subclasses(type, name, callback, data);
-}
-
-static int
-recurse_down_subclasses(PyTypeObject *type, PyObject *name,
- update_callback callback, void *data)
-{
- PyTypeObject *subclass;
- PyObject *ref, *subclasses, *dict;
- Py_ssize_t i, n;
-
- subclasses = type->tp_subclasses;
- if (subclasses == NULL)
- return 0;
- assert(PyList_Check(subclasses));
- n = PyList_GET_SIZE(subclasses);
- for (i = 0; i < n; i++) {
- ref = PyList_GET_ITEM(subclasses, i);
- assert(PyWeakref_CheckRef(ref));
- subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);
- assert(subclass != NULL);
- if ((PyObject *)subclass == Py_None)
- continue;
- assert(PyType_Check(subclass));
- /* Avoid recursing down into unaffected classes */
- dict = subclass->tp_dict;
- if (dict != NULL && PyDict_Check(dict) &&
- PyDict_GetItem(dict, name) != NULL)
- continue;
- if (update_subclasses(subclass, name, callback, data) < 0)
- return -1;
- }
- return 0;
-}
-
-/* This function is called by PyType_Ready() to populate the type's
- dictionary with method descriptors for function slots. For each
- function slot (like tp_repr) that's defined in the type, one or more
- corresponding descriptors are added in the type's tp_dict dictionary
- under the appropriate name (like __repr__). Some function slots
- cause more than one descriptor to be added (for example, the nb_add
- slot adds both __add__ and __radd__ descriptors) and some function
- slots compete for the same descriptor (for example both sq_item and
- mp_subscript generate a __getitem__ descriptor).
-
- In the latter case, the first slotdef entry encoutered wins. Since
- slotdef entries are sorted by the offset of the slot in the
- PyHeapTypeObject, this gives us some control over disambiguating
- between competing slots: the members of PyHeapTypeObject are listed
- from most general to least general, so the most general slot is
- preferred. In particular, because as_mapping comes before as_sequence,
- for a type that defines both mp_subscript and sq_item, mp_subscript
- wins.
-
- This only adds new descriptors and doesn't overwrite entries in
- tp_dict that were previously defined. The descriptors contain a
- reference to the C function they must call, so that it's safe if they
- are copied into a subtype's __dict__ and the subtype has a different
- C function in its slot -- calling the method defined by the
- descriptor will call the C function that was used to create it,
- rather than the C function present in the slot when it is called.
- (This is important because a subtype may have a C function in the
- slot that calls the method from the dictionary, and we want to avoid
- infinite recursion here.) */
-
-static int
-add_operators(PyTypeObject *type)
-{
- PyObject *dict = type->tp_dict;
- slotdef *p;
- PyObject *descr;
- void **ptr;
-
- init_slotdefs();
- for (p = slotdefs; p->name; p++) {
- if (p->wrapper == NULL)
- continue;
- ptr = slotptr(type, p->offset);
- if (!ptr || !*ptr)
- continue;
- if (PyDict_GetItem(dict, p->name_strobj))
- continue;
- descr = PyDescr_NewWrapper(type, p, *ptr);
- if (descr == NULL)
- return -1;
- if (PyDict_SetItem(dict, p->name_strobj, descr) < 0)
- return -1;
- Py_DECREF(descr);
- }
- if (type->tp_new != NULL) {
- if (add_tp_new_wrapper(type) < 0)
- return -1;
- }
- return 0;
-}
-
-
-/* Cooperative 'super' */
-
-typedef struct {
- PyObject_HEAD
- PyTypeObject *type;
- PyObject *obj;
- PyTypeObject *obj_type;
-} superobject;
-
-static PyMemberDef super_members[] = {
- {"__thisclass__", T_OBJECT, offsetof(superobject, type), READONLY,
- "the class invoking super()"},
- {"__self__", T_OBJECT, offsetof(superobject, obj), READONLY,
- "the instance invoking super(); may be None"},
- {"__self_class__", T_OBJECT, offsetof(superobject, obj_type), READONLY,
- "the type of the instance invoking super(); may be None"},
- {0}
-};
-
-static void
-super_dealloc(PyObject *self)
-{
- superobject *su = (superobject *)self;
-
- _PyObject_GC_UNTRACK(self);
- Py_XDECREF(su->obj);
- Py_XDECREF(su->type);
- Py_XDECREF(su->obj_type);
- self->ob_type->tp_free(self);
-}
-
-static PyObject *
-super_repr(PyObject *self)
-{
- superobject *su = (superobject *)self;
-
- if (su->obj_type)
- return PyString_FromFormat(
- "<super: <class '%s'>, <%s object>>",
- su->type ? su->type->tp_name : "NULL",
- su->obj_type->tp_name);
- else
- return PyString_FromFormat(
- "<super: <class '%s'>, NULL>",
- su->type ? su->type->tp_name : "NULL");
-}
-
-static PyObject *
-super_getattro(PyObject *self, PyObject *name)
-{
- superobject *su = (superobject *)self;
- int skip = su->obj_type == NULL;
-
- if (!skip) {
- /* We want __class__ to return the class of the super object
- (i.e. super, or a subclass), not the class of su->obj. */
- skip = (PyString_Check(name) &&
- PyString_GET_SIZE(name) == 9 &&
- strcmp(PyString_AS_STRING(name), "__class__") == 0);
- }
-
- if (!skip) {
- PyObject *mro, *res, *tmp, *dict;
- PyTypeObject *starttype;
- descrgetfunc f;
- Py_ssize_t i, n;
-
- starttype = su->obj_type;
- mro = starttype->tp_mro;
-
- if (mro == NULL)
- n = 0;
- else {
- assert(PyTuple_Check(mro));
- n = PyTuple_GET_SIZE(mro);
- }
- for (i = 0; i < n; i++) {
- if ((PyObject *)(su->type) == PyTuple_GET_ITEM(mro, i))
- break;
- }
- i++;
- res = NULL;
- for (; i < n; i++) {
- tmp = PyTuple_GET_ITEM(mro, i);
- if (PyType_Check(tmp))
- dict = ((PyTypeObject *)tmp)->tp_dict;
- else if (PyClass_Check(tmp))
- dict = ((PyClassObject *)tmp)->cl_dict;
- else
- continue;
- res = PyDict_GetItem(dict, name);
- if (res != NULL) {
- Py_INCREF(res);
- f = res->ob_type->tp_descr_get;
- if (f != NULL) {
- tmp = f(res,
- /* Only pass 'obj' param if
- this is instance-mode super
- (See SF ID #743627)
- */
- (su->obj == (PyObject *)
- su->obj_type
- ? (PyObject *)NULL
- : su->obj),
- (PyObject *)starttype);
- Py_DECREF(res);
- res = tmp;
- }
- return res;
- }
- }
- }
- return PyObject_GenericGetAttr(self, name);
-}
-
-static PyTypeObject *
-supercheck(PyTypeObject *type, PyObject *obj)
-{
- /* Check that a super() call makes sense. Return a type object.
-
- obj can be a new-style class, or an instance of one:
-
- - If it is a class, it must be a subclass of 'type'. This case is
- used for class methods; the return value is obj.
-
- - If it is an instance, it must be an instance of 'type'. This is
- the normal case; the return value is obj.__class__.
-
- But... when obj is an instance, we want to allow for the case where
- obj->ob_type is not a subclass of type, but obj.__class__ is!
- This will allow using super() with a proxy for obj.
- */
-
- /* Check for first bullet above (special case) */
- if (PyType_Check(obj) && PyType_IsSubtype((PyTypeObject *)obj, type)) {
- Py_INCREF(obj);
- return (PyTypeObject *)obj;
- }
-
- /* Normal case */
- if (PyType_IsSubtype(obj->ob_type, type)) {
- Py_INCREF(obj->ob_type);
- return obj->ob_type;
- }
- else {
- /* Try the slow way */
- static PyObject *class_str = NULL;
- PyObject *class_attr;
-
- if (class_str == NULL) {
- class_str = PyString_FromString("__class__");
- if (class_str == NULL)
- return NULL;
- }
-
- class_attr = PyObject_GetAttr(obj, class_str);
-
- if (class_attr != NULL &&
- PyType_Check(class_attr) &&
- (PyTypeObject *)class_attr != obj->ob_type)
- {
- int ok = PyType_IsSubtype(
- (PyTypeObject *)class_attr, type);
- if (ok)
- return (PyTypeObject *)class_attr;
- }
-
- if (class_attr == NULL)
- PyErr_Clear();
- else
- Py_DECREF(class_attr);
- }
-
- PyErr_SetString(PyExc_TypeError,
- "super(type, obj): "
- "obj must be an instance or subtype of type");
- return NULL;
-}
-
-static PyObject *
-super_descr_get(PyObject *self, PyObject *obj, PyObject *type)
-{
- superobject *su = (superobject *)self;
- superobject *newobj;
-
- if (obj == NULL || obj == Py_None || su->obj != NULL) {
- /* Not binding to an object, or already bound */
- Py_INCREF(self);
- return self;
- }
- if (su->ob_type != &PySuper_Type)
- /* If su is an instance of a (strict) subclass of super,
- call its type */
- return PyObject_CallFunctionObjArgs((PyObject *)su->ob_type,
- su->type, obj, NULL);
- else {
- /* Inline the common case */
- PyTypeObject *obj_type = supercheck(su->type, obj);
- if (obj_type == NULL)
- return NULL;
- newobj = (superobject *)PySuper_Type.tp_new(&PySuper_Type,
- NULL, NULL);
- if (newobj == NULL)
- return NULL;
- Py_INCREF(su->type);
- Py_INCREF(obj);
- newobj->type = su->type;
- newobj->obj = obj;
- newobj->obj_type = obj_type;
- return (PyObject *)newobj;
- }
-}
-
-static int
-super_init(PyObject *self, PyObject *args, PyObject *kwds)
-{
- superobject *su = (superobject *)self;
- PyTypeObject *type;
- PyObject *obj = NULL;
- PyTypeObject *obj_type = NULL;
-
- if (!_PyArg_NoKeywords("super", kwds))
- return -1;
- if (!PyArg_ParseTuple(args, "O!|O:super", &PyType_Type, &type, &obj))
- return -1;
- if (obj == Py_None)
- obj = NULL;
- if (obj != NULL) {
- obj_type = supercheck(type, obj);
- if (obj_type == NULL)
- return -1;
- Py_INCREF(obj);
- }
- Py_INCREF(type);
- su->type = type;
- su->obj = obj;
- su->obj_type = obj_type;
- return 0;
-}
-
-PyDoc_STRVAR(super_doc,
-"super(type) -> unbound super object\n"
-"super(type, obj) -> bound super object; requires isinstance(obj, type)\n"
-"super(type, type2) -> bound super object; requires issubclass(type2, type)\n"
-"Typical use to call a cooperative superclass method:\n"
-"class C(B):\n"
-" def meth(self, arg):\n"
-" super(C, self).meth(arg)");
-
-static int
-super_traverse(PyObject *self, visitproc visit, void *arg)
-{
- superobject *su = (superobject *)self;
-
- Py_VISIT(su->obj);
- Py_VISIT(su->type);
- Py_VISIT(su->obj_type);
-
- return 0;
-}
-
-PyTypeObject PySuper_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "super", /* tp_name */
- sizeof(superobject), /* tp_basicsize */
- 0, /* tp_itemsize */
- /* methods */
- super_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- super_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- super_getattro, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- super_doc, /* tp_doc */
- super_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- 0, /* tp_methods */
- super_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- super_descr_get, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- super_init, /* tp_init */
- PyType_GenericAlloc, /* tp_alloc */
- PyType_GenericNew, /* tp_new */
- PyObject_GC_Del, /* tp_free */
-};
diff --git a/sys/src/cmd/python/Objects/unicodectype.c b/sys/src/cmd/python/Objects/unicodectype.c
deleted file mode 100644
index 73def09db..000000000
--- a/sys/src/cmd/python/Objects/unicodectype.c
+++ /dev/null
@@ -1,789 +0,0 @@
-/*
- Unicode character type helpers.
-
- Written by Marc-Andre Lemburg (mal@lemburg.com).
- Modified for Python 2.0 by Fredrik Lundh (fredrik@pythonware.com)
-
- Copyright (c) Corporation for National Research Initiatives.
-
-*/
-
-#include "Python.h"
-#include "unicodeobject.h"
-
-#define ALPHA_MASK 0x01
-#define DECIMAL_MASK 0x02
-#define DIGIT_MASK 0x04
-#define LOWER_MASK 0x08
-#define LINEBREAK_MASK 0x10
-#define SPACE_MASK 0x20
-#define TITLE_MASK 0x40
-#define UPPER_MASK 0x80
-
-typedef struct {
- const Py_UNICODE upper;
- const Py_UNICODE lower;
- const Py_UNICODE title;
- const unsigned char decimal;
- const unsigned char digit;
- const unsigned short flags;
-} _PyUnicode_TypeRecord;
-
-#include "unicodetype_db.h"
-
-static const _PyUnicode_TypeRecord *
-gettyperecord(Py_UNICODE code)
-{
- int index;
-
-#ifdef Py_UNICODE_WIDE
- if (code >= 0x110000)
- index = 0;
- else
-#endif
- {
- index = index1[(code>>SHIFT)];
- index = index2[(index<<SHIFT)+(code&((1<<SHIFT)-1))];
- }
-
- return &_PyUnicode_TypeRecords[index];
-}
-
-/* Returns 1 for Unicode characters having the category 'Zl', 'Zp' or
- type 'B', 0 otherwise. */
-
-int _PyUnicode_IsLinebreak(register const Py_UNICODE ch)
-{
- switch (ch) {
- case 0x000A: /* LINE FEED */
- case 0x000D: /* CARRIAGE RETURN */
- case 0x001C: /* FILE SEPARATOR */
- case 0x001D: /* GROUP SEPARATOR */
- case 0x001E: /* RECORD SEPARATOR */
- case 0x0085: /* NEXT LINE */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- return 1;
- default:
- return 0;
- }
-}
-
-/* Returns the titlecase Unicode characters corresponding to ch or just
- ch if no titlecase mapping is known. */
-
-Py_UNICODE _PyUnicode_ToTitlecase(register Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
- int delta;
-
- if (ctype->title)
- delta = ctype->title;
- else
- delta = ctype->upper;
-
- if (delta >= 32768)
- delta -= 65536;
-
- return ch + delta;
-}
-
-/* Returns 1 for Unicode characters having the category 'Lt', 0
- otherwise. */
-
-int _PyUnicode_IsTitlecase(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
-
- return (ctype->flags & TITLE_MASK) != 0;
-}
-
-/* Returns the integer decimal (0-9) for Unicode characters having
- this property, -1 otherwise. */
-
-int _PyUnicode_ToDecimalDigit(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
-
- return (ctype->flags & DECIMAL_MASK) ? ctype->decimal : -1;
-}
-
-int _PyUnicode_IsDecimalDigit(Py_UNICODE ch)
-{
- if (_PyUnicode_ToDecimalDigit(ch) < 0)
- return 0;
- return 1;
-}
-
-/* Returns the integer digit (0-9) for Unicode characters having
- this property, -1 otherwise. */
-
-int _PyUnicode_ToDigit(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
-
- return (ctype->flags & DIGIT_MASK) ? ctype->digit : -1;
-}
-
-int _PyUnicode_IsDigit(Py_UNICODE ch)
-{
- if (_PyUnicode_ToDigit(ch) < 0)
- return 0;
- return 1;
-}
-
-/* Returns the numeric value as double for Unicode characters having
- this property, -1.0 otherwise. */
-
-/* TODO: replace with unicodetype_db.h table */
-
-double _PyUnicode_ToNumeric(Py_UNICODE ch)
-{
- switch (ch) {
- case 0x0F33:
- return (double) -1 / 2;
- case 0x17F0:
- case 0x3007:
-#ifdef Py_UNICODE_WIDE
- case 0x1018A:
-#endif
- return (double) 0;
- case 0x09F4:
- case 0x17F1:
- case 0x215F:
- case 0x2160:
- case 0x2170:
- case 0x3021:
- case 0x3192:
- case 0x3220:
- case 0x3280:
-#ifdef Py_UNICODE_WIDE
- case 0x10107:
- case 0x10142:
- case 0x10158:
- case 0x10159:
- case 0x1015A:
- case 0x10320:
- case 0x103D1:
-#endif
- return (double) 1;
- case 0x00BD:
- case 0x0F2A:
- case 0x2CFD:
-#ifdef Py_UNICODE_WIDE
- case 0x10141:
- case 0x10175:
- case 0x10176:
-#endif
- return (double) 1 / 2;
- case 0x2153:
- return (double) 1 / 3;
- case 0x00BC:
-#ifdef Py_UNICODE_WIDE
- case 0x10140:
-#endif
- return (double) 1 / 4;
- case 0x2155:
- return (double) 1 / 5;
- case 0x2159:
- return (double) 1 / 6;
- case 0x215B:
- return (double) 1 / 8;
- case 0x0BF0:
- case 0x1372:
- case 0x2169:
- case 0x2179:
- case 0x2469:
- case 0x247D:
- case 0x2491:
- case 0x24FE:
- case 0x277F:
- case 0x2789:
- case 0x2793:
- case 0x3038:
- case 0x3229:
- case 0x3289:
-#ifdef Py_UNICODE_WIDE
- case 0x10110:
- case 0x10149:
- case 0x10150:
- case 0x10157:
- case 0x10160:
- case 0x10161:
- case 0x10162:
- case 0x10163:
- case 0x10164:
- case 0x10322:
- case 0x103D3:
- case 0x10A44:
-#endif
- return (double) 10;
- case 0x0BF1:
- case 0x137B:
- case 0x216D:
- case 0x217D:
-#ifdef Py_UNICODE_WIDE
- case 0x10119:
- case 0x1014B:
- case 0x10152:
- case 0x1016A:
- case 0x103D5:
- case 0x10A46:
-#endif
- return (double) 100;
- case 0x0BF2:
- case 0x216F:
- case 0x217F:
- case 0x2180:
-#ifdef Py_UNICODE_WIDE
- case 0x10122:
- case 0x1014D:
- case 0x10154:
- case 0x10171:
- case 0x10A47:
-#endif
- return (double) 1000;
- case 0x137C:
- case 0x2182:
-#ifdef Py_UNICODE_WIDE
- case 0x1012B:
- case 0x10155:
-#endif
- return (double) 10000;
- case 0x216A:
- case 0x217A:
- case 0x246A:
- case 0x247E:
- case 0x2492:
- case 0x24EB:
- return (double) 11;
- case 0x0F2F:
- return (double) 11 / 2;
- case 0x216B:
- case 0x217B:
- case 0x246B:
- case 0x247F:
- case 0x2493:
- case 0x24EC:
- return (double) 12;
- case 0x246C:
- case 0x2480:
- case 0x2494:
- case 0x24ED:
- return (double) 13;
- case 0x0F30:
- return (double) 13 / 2;
- case 0x246D:
- case 0x2481:
- case 0x2495:
- case 0x24EE:
- return (double) 14;
- case 0x246E:
- case 0x2482:
- case 0x2496:
- case 0x24EF:
- return (double) 15;
- case 0x0F31:
- return (double) 15 / 2;
- case 0x09F9:
- case 0x246F:
- case 0x2483:
- case 0x2497:
- case 0x24F0:
- return (double) 16;
- case 0x16EE:
- case 0x2470:
- case 0x2484:
- case 0x2498:
- case 0x24F1:
- return (double) 17;
- case 0x0F32:
- return (double) 17 / 2;
- case 0x16EF:
- case 0x2471:
- case 0x2485:
- case 0x2499:
- case 0x24F2:
- return (double) 18;
- case 0x16F0:
- case 0x2472:
- case 0x2486:
- case 0x249A:
- case 0x24F3:
- return (double) 19;
- case 0x09F5:
- case 0x17F2:
- case 0x2161:
- case 0x2171:
- case 0x3022:
- case 0x3193:
- case 0x3221:
- case 0x3281:
-#ifdef Py_UNICODE_WIDE
- case 0x10108:
- case 0x1015B:
- case 0x1015C:
- case 0x1015D:
- case 0x1015E:
- case 0x103D2:
-#endif
- return (double) 2;
- case 0x2154:
-#ifdef Py_UNICODE_WIDE
- case 0x10177:
-#endif
- return (double) 2 / 3;
- case 0x2156:
- return (double) 2 / 5;
- case 0x1373:
- case 0x2473:
- case 0x2487:
- case 0x249B:
- case 0x24F4:
- case 0x3039:
-#ifdef Py_UNICODE_WIDE
- case 0x10111:
- case 0x103D4:
- case 0x10A45:
-#endif
- return (double) 20;
-#ifdef Py_UNICODE_WIDE
- case 0x1011A:
- return (double) 200;
- case 0x10123:
- return (double) 2000;
- case 0x1012C:
- return (double) 20000;
-#endif
- case 0x3251:
- return (double) 21;
- case 0x3252:
- return (double) 22;
- case 0x3253:
- return (double) 23;
- case 0x3254:
- return (double) 24;
- case 0x3255:
- return (double) 25;
- case 0x3256:
- return (double) 26;
- case 0x3257:
- return (double) 27;
- case 0x3258:
- return (double) 28;
- case 0x3259:
- return (double) 29;
- case 0x09F6:
- case 0x17F3:
- case 0x2162:
- case 0x2172:
- case 0x3023:
- case 0x3194:
- case 0x3222:
- case 0x3282:
-#ifdef Py_UNICODE_WIDE
- case 0x10109:
-#endif
- return (double) 3;
- case 0x0F2B:
- return (double) 3 / 2;
- case 0x00BE:
-#ifdef Py_UNICODE_WIDE
- case 0x10178:
-#endif
- return (double) 3 / 4;
- case 0x2157:
- return (double) 3 / 5;
- case 0x215C:
- return (double) 3 / 8;
- case 0x1374:
- case 0x303A:
- case 0x325A:
-#ifdef Py_UNICODE_WIDE
- case 0x10112:
- case 0x10165:
-#endif
- return (double) 30;
-#ifdef Py_UNICODE_WIDE
- case 0x1011B:
- case 0x1016B:
- return (double) 300;
- case 0x10124:
- return (double) 3000;
- case 0x1012D:
- return (double) 30000;
-#endif
- case 0x325B:
- return (double) 31;
- case 0x325C:
- return (double) 32;
- case 0x325D:
- return (double) 33;
- case 0x325E:
- return (double) 34;
- case 0x325F:
- return (double) 35;
- case 0x32B1:
- return (double) 36;
- case 0x32B2:
- return (double) 37;
- case 0x32B3:
- return (double) 38;
- case 0x32B4:
- return (double) 39;
- case 0x09F7:
- case 0x17F4:
- case 0x2163:
- case 0x2173:
- case 0x3024:
- case 0x3195:
- case 0x3223:
- case 0x3283:
-#ifdef Py_UNICODE_WIDE
- case 0x1010A:
-#endif
- return (double) 4;
- case 0x2158:
- return (double) 4 / 5;
- case 0x1375:
- case 0x32B5:
-#ifdef Py_UNICODE_WIDE
- case 0x10113:
-#endif
- return (double) 40;
-#ifdef Py_UNICODE_WIDE
- case 0x1011C:
- return (double) 400;
- case 0x10125:
- return (double) 4000;
- case 0x1012E:
- return (double) 40000;
-#endif
- case 0x32B6:
- return (double) 41;
- case 0x32B7:
- return (double) 42;
- case 0x32B8:
- return (double) 43;
- case 0x32B9:
- return (double) 44;
- case 0x32BA:
- return (double) 45;
- case 0x32BB:
- return (double) 46;
- case 0x32BC:
- return (double) 47;
- case 0x32BD:
- return (double) 48;
- case 0x32BE:
- return (double) 49;
- case 0x17F5:
- case 0x2164:
- case 0x2174:
- case 0x3025:
- case 0x3224:
- case 0x3284:
-#ifdef Py_UNICODE_WIDE
- case 0x1010B:
- case 0x10143:
- case 0x10148:
- case 0x1014F:
- case 0x1015F:
- case 0x10173:
- case 0x10321:
-#endif
- return (double) 5;
- case 0x0F2C:
- return (double) 5 / 2;
- case 0x215A:
- return (double) 5 / 6;
- case 0x215D:
- return (double) 5 / 8;
- case 0x1376:
- case 0x216C:
- case 0x217C:
- case 0x32BF:
-#ifdef Py_UNICODE_WIDE
- case 0x10114:
- case 0x10144:
- case 0x1014A:
- case 0x10151:
- case 0x10166:
- case 0x10167:
- case 0x10168:
- case 0x10169:
- case 0x10174:
- case 0x10323:
-#endif
- return (double) 50;
- case 0x216E:
- case 0x217E:
-#ifdef Py_UNICODE_WIDE
- case 0x1011D:
- case 0x10145:
- case 0x1014C:
- case 0x10153:
- case 0x1016C:
- case 0x1016D:
- case 0x1016E:
- case 0x1016F:
- case 0x10170:
-#endif
- return (double) 500;
- case 0x2181:
-#ifdef Py_UNICODE_WIDE
- case 0x10126:
- case 0x10146:
- case 0x1014E:
- case 0x10172:
-#endif
- return (double) 5000;
-#ifdef Py_UNICODE_WIDE
- case 0x1012F:
- case 0x10147:
- case 0x10156:
- return (double) 50000;
-#endif
- case 0x17F6:
- case 0x2165:
- case 0x2175:
- case 0x3026:
- case 0x3225:
- case 0x3285:
-#ifdef Py_UNICODE_WIDE
- case 0x1010C:
-#endif
- return (double) 6;
- case 0x1377:
-#ifdef Py_UNICODE_WIDE
- case 0x10115:
-#endif
- return (double) 60;
-#ifdef Py_UNICODE_WIDE
- case 0x1011E:
- return (double) 600;
- case 0x10127:
- return (double) 6000;
- case 0x10130:
- return (double) 60000;
-#endif
- case 0x17F7:
- case 0x2166:
- case 0x2176:
- case 0x3027:
- case 0x3226:
- case 0x3286:
-#ifdef Py_UNICODE_WIDE
- case 0x1010D:
-#endif
- return (double) 7;
- case 0x0F2D:
- return (double) 7 / 2;
- case 0x215E:
- return (double) 7 / 8;
- case 0x1378:
-#ifdef Py_UNICODE_WIDE
- case 0x10116:
-#endif
- return (double) 70;
-#ifdef Py_UNICODE_WIDE
- case 0x1011F:
- return (double) 700;
- case 0x10128:
- return (double) 7000;
- case 0x10131:
- return (double) 70000;
-#endif
- case 0x17F8:
- case 0x2167:
- case 0x2177:
- case 0x3028:
- case 0x3227:
- case 0x3287:
-#ifdef Py_UNICODE_WIDE
- case 0x1010E:
-#endif
- return (double) 8;
- case 0x1379:
-#ifdef Py_UNICODE_WIDE
- case 0x10117:
-#endif
- return (double) 80;
-#ifdef Py_UNICODE_WIDE
- case 0x10120:
- return (double) 800;
- case 0x10129:
- return (double) 8000;
- case 0x10132:
- return (double) 80000;
-#endif
- case 0x17F9:
- case 0x2168:
- case 0x2178:
- case 0x3029:
- case 0x3228:
- case 0x3288:
-#ifdef Py_UNICODE_WIDE
- case 0x1010F:
-#endif
- return (double) 9;
- case 0x0F2E:
- return (double) 9 / 2;
- case 0x137A:
-#ifdef Py_UNICODE_WIDE
- case 0x10118:
-#endif
- return (double) 90;
-#ifdef Py_UNICODE_WIDE
- case 0x10121:
- case 0x1034A:
- return (double) 900;
- case 0x1012A:
- return (double) 9000;
- case 0x10133:
- return (double) 90000;
-#endif
- default:
- return (double) _PyUnicode_ToDigit(ch);
- }
-}
-
-int _PyUnicode_IsNumeric(Py_UNICODE ch)
-{
- return _PyUnicode_ToNumeric(ch) != -1.0;
-}
-
-#ifndef WANT_WCTYPE_FUNCTIONS
-
-/* Returns 1 for Unicode characters having the bidirectional type
- 'WS', 'B' or 'S' or the category 'Zs', 0 otherwise. */
-
-int _PyUnicode_IsWhitespace(register const Py_UNICODE ch)
-{
- switch (ch) {
- case 0x0009: /* HORIZONTAL TABULATION */
- case 0x000A: /* LINE FEED */
- case 0x000B: /* VERTICAL TABULATION */
- case 0x000C: /* FORM FEED */
- case 0x000D: /* CARRIAGE RETURN */
- case 0x001C: /* FILE SEPARATOR */
- case 0x001D: /* GROUP SEPARATOR */
- case 0x001E: /* RECORD SEPARATOR */
- case 0x001F: /* UNIT SEPARATOR */
- case 0x0020: /* SPACE */
- case 0x0085: /* NEXT LINE */
- case 0x00A0: /* NO-BREAK SPACE */
- case 0x1680: /* OGHAM SPACE MARK */
- case 0x2000: /* EN QUAD */
- case 0x2001: /* EM QUAD */
- case 0x2002: /* EN SPACE */
- case 0x2003: /* EM SPACE */
- case 0x2004: /* THREE-PER-EM SPACE */
- case 0x2005: /* FOUR-PER-EM SPACE */
- case 0x2006: /* SIX-PER-EM SPACE */
- case 0x2007: /* FIGURE SPACE */
- case 0x2008: /* PUNCTUATION SPACE */
- case 0x2009: /* THIN SPACE */
- case 0x200A: /* HAIR SPACE */
- case 0x200B: /* ZERO WIDTH SPACE */
- case 0x2028: /* LINE SEPARATOR */
- case 0x2029: /* PARAGRAPH SEPARATOR */
- case 0x202F: /* NARROW NO-BREAK SPACE */
- case 0x205F: /* MEDIUM MATHEMATICAL SPACE */
- case 0x3000: /* IDEOGRAPHIC SPACE */
- return 1;
- default:
- return 0;
- }
-}
-
-/* Returns 1 for Unicode characters having the category 'Ll', 0
- otherwise. */
-
-int _PyUnicode_IsLowercase(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
-
- return (ctype->flags & LOWER_MASK) != 0;
-}
-
-/* Returns 1 for Unicode characters having the category 'Lu', 0
- otherwise. */
-
-int _PyUnicode_IsUppercase(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
-
- return (ctype->flags & UPPER_MASK) != 0;
-}
-
-/* Returns the uppercase Unicode characters corresponding to ch or just
- ch if no uppercase mapping is known. */
-
-Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
- int delta = ctype->upper;
- if (delta >= 32768)
- delta -= 65536;
- return ch + delta;
-}
-
-/* Returns the lowercase Unicode characters corresponding to ch or just
- ch if no lowercase mapping is known. */
-
-Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
- int delta = ctype->lower;
- if (delta >= 32768)
- delta -= 65536;
- return ch + delta;
-}
-
-/* Returns 1 for Unicode characters having the category 'Ll', 'Lu', 'Lt',
- 'Lo' or 'Lm', 0 otherwise. */
-
-int _PyUnicode_IsAlpha(Py_UNICODE ch)
-{
- const _PyUnicode_TypeRecord *ctype = gettyperecord(ch);
-
- return (ctype->flags & ALPHA_MASK) != 0;
-}
-
-#else
-
-/* Export the interfaces using the wchar_t type for portability
- reasons: */
-
-int _PyUnicode_IsWhitespace(Py_UNICODE ch)
-{
- return iswspace(ch);
-}
-
-int _PyUnicode_IsLowercase(Py_UNICODE ch)
-{
- return iswlower(ch);
-}
-
-int _PyUnicode_IsUppercase(Py_UNICODE ch)
-{
- return iswupper(ch);
-}
-
-Py_UNICODE _PyUnicode_ToLowercase(Py_UNICODE ch)
-{
- return towlower(ch);
-}
-
-Py_UNICODE _PyUnicode_ToUppercase(Py_UNICODE ch)
-{
- return towupper(ch);
-}
-
-int _PyUnicode_IsAlpha(Py_UNICODE ch)
-{
- return iswalpha(ch);
-}
-
-#endif
diff --git a/sys/src/cmd/python/Objects/unicodeobject.c b/sys/src/cmd/python/Objects/unicodeobject.c
deleted file mode 100644
index 00f2018da..000000000
--- a/sys/src/cmd/python/Objects/unicodeobject.c
+++ /dev/null
@@ -1,8067 +0,0 @@
-/*
-
-Unicode implementation based on original code by Fredrik Lundh,
-modified by Marc-Andre Lemburg <mal@lemburg.com> according to the
-Unicode Integration Proposal (see file Misc/unicode.txt).
-
-Major speed upgrades to the method implementations at the Reykjavik
-NeedForSpeed sprint, by Fredrik Lundh and Andrew Dalke.
-
-Copyright (c) Corporation for National Research Initiatives.
-
---------------------------------------------------------------------
-The original string type implementation is:
-
- Copyright (c) 1999 by Secret Labs AB
- Copyright (c) 1999 by Fredrik Lundh
-
-By obtaining, using, and/or copying this software and/or its
-associated documentation, you agree that you have read, understood,
-and will comply with the following terms and conditions:
-
-Permission to use, copy, modify, and distribute this software and its
-associated documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appears in all
-copies, and that both that copyright notice and this permission notice
-appear in supporting documentation, and that the name of Secret Labs
-AB or the author not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
-THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
-FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR 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.
---------------------------------------------------------------------
-
-*/
-
-#define PY_SSIZE_T_CLEAN
-#include "Python.h"
-
-#include "unicodeobject.h"
-#include "ucnhash.h"
-
-#ifdef MS_WINDOWS
-#include <windows.h>
-#endif
-
-/* Limit for the Unicode object free list */
-
-#define MAX_UNICODE_FREELIST_SIZE 1024
-
-/* Limit for the Unicode object free list stay alive optimization.
-
- The implementation will keep allocated Unicode memory intact for
- all objects on the free list having a size less than this
- limit. This reduces malloc() overhead for small Unicode objects.
-
- At worst this will result in MAX_UNICODE_FREELIST_SIZE *
- (sizeof(PyUnicodeObject) + KEEPALIVE_SIZE_LIMIT +
- malloc()-overhead) bytes of unused garbage.
-
- Setting the limit to 0 effectively turns the feature off.
-
- Note: This is an experimental feature ! If you get core dumps when
- using Unicode objects, turn this feature off.
-
-*/
-
-#define KEEPALIVE_SIZE_LIMIT 9
-
-/* Endianness switches; defaults to little endian */
-
-#ifdef WORDS_BIGENDIAN
-# define BYTEORDER_IS_BIG_ENDIAN
-#else
-# define BYTEORDER_IS_LITTLE_ENDIAN
-#endif
-
-/* --- Globals ------------------------------------------------------------
-
- The globals are initialized by the _PyUnicode_Init() API and should
- not be used before calling that API.
-
-*/
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Free list for Unicode objects */
-static PyUnicodeObject *unicode_freelist;
-static int unicode_freelist_size;
-
-/* The empty Unicode object is shared to improve performance. */
-static PyUnicodeObject *unicode_empty;
-
-/* Single character Unicode strings in the Latin-1 range are being
- shared as well. */
-static PyUnicodeObject *unicode_latin1[256];
-
-/* Default encoding to use and assume when NULL is passed as encoding
- parameter; it is initialized by _PyUnicode_Init().
-
- Always use the PyUnicode_SetDefaultEncoding() and
- PyUnicode_GetDefaultEncoding() APIs to access this global.
-
-*/
-static char unicode_default_encoding[100];
-
-Py_UNICODE
-PyUnicode_GetMax(void)
-{
-#ifdef Py_UNICODE_WIDE
- return 0x10FFFF;
-#else
- /* This is actually an illegal character, so it should
- not be passed to unichr. */
- return 0xFFFF;
-#endif
-}
-
-/* --- Bloom Filters ----------------------------------------------------- */
-
-/* stuff to implement simple "bloom filters" for Unicode characters.
- to keep things simple, we use a single bitmask, using the least 5
- bits from each unicode characters as the bit index. */
-
-/* the linebreak mask is set up by Unicode_Init below */
-
-#define BLOOM_MASK unsigned long
-
-static BLOOM_MASK bloom_linebreak;
-
-#define BLOOM(mask, ch) ((mask & (1 << ((ch) & 0x1F))))
-
-#define BLOOM_LINEBREAK(ch)\
- (BLOOM(bloom_linebreak, (ch)) && Py_UNICODE_ISLINEBREAK((ch)))
-
-Py_LOCAL_INLINE(BLOOM_MASK) make_bloom_mask(Py_UNICODE* ptr, Py_ssize_t len)
-{
- /* calculate simple bloom-style bitmask for a given unicode string */
-
- long mask;
- Py_ssize_t i;
-
- mask = 0;
- for (i = 0; i < len; i++)
- mask |= (1 << (ptr[i] & 0x1F));
-
- return mask;
-}
-
-Py_LOCAL_INLINE(int) unicode_member(Py_UNICODE chr, Py_UNICODE* set, Py_ssize_t setlen)
-{
- Py_ssize_t i;
-
- for (i = 0; i < setlen; i++)
- if (set[i] == chr)
- return 1;
-
- return 0;
-}
-
-#define BLOOM_MEMBER(mask, chr, set, setlen)\
- BLOOM(mask, chr) && unicode_member(chr, set, setlen)
-
-/* --- Unicode Object ----------------------------------------------------- */
-
-static
-int unicode_resize(register PyUnicodeObject *unicode,
- Py_ssize_t length)
-{
- void *oldstr;
-
- /* Shortcut if there's nothing much to do. */
- if (unicode->length == length)
- goto reset;
-
- /* Resizing shared object (unicode_empty or single character
- objects) in-place is not allowed. Use PyUnicode_Resize()
- instead ! */
-
- if (unicode == unicode_empty ||
- (unicode->length == 1 &&
- unicode->str[0] < 256U &&
- unicode_latin1[unicode->str[0]] == unicode)) {
- PyErr_SetString(PyExc_SystemError,
- "can't resize shared unicode objects");
- return -1;
- }
-
- /* We allocate one more byte to make sure the string is Ux0000 terminated.
- The overallocation is also used by fastsearch, which assumes that it's
- safe to look at str[length] (without making any assumptions about what
- it contains). */
-
- oldstr = unicode->str;
- PyMem_RESIZE(unicode->str, Py_UNICODE, length + 1);
- if (!unicode->str) {
- unicode->str = (Py_UNICODE *)oldstr;
- PyErr_NoMemory();
- return -1;
- }
- unicode->str[length] = 0;
- unicode->length = length;
-
- reset:
- /* Reset the object caches */
- if (unicode->defenc) {
- Py_DECREF(unicode->defenc);
- unicode->defenc = NULL;
- }
- unicode->hash = -1;
-
- return 0;
-}
-
-/* We allocate one more byte to make sure the string is
- Ux0000 terminated -- XXX is this needed ?
-
- XXX This allocator could further be enhanced by assuring that the
- free list never reduces its size below 1.
-
-*/
-
-static
-PyUnicodeObject *_PyUnicode_New(Py_ssize_t length)
-{
- register PyUnicodeObject *unicode;
-
- /* Optimization for empty strings */
- if (length == 0 && unicode_empty != NULL) {
- Py_INCREF(unicode_empty);
- return unicode_empty;
- }
-
- /* Unicode freelist & memory allocation */
- if (unicode_freelist) {
- unicode = unicode_freelist;
- unicode_freelist = *(PyUnicodeObject **)unicode;
- unicode_freelist_size--;
- if (unicode->str) {
- /* Keep-Alive optimization: we only upsize the buffer,
- never downsize it. */
- if ((unicode->length < length) &&
- unicode_resize(unicode, length) < 0) {
- PyMem_DEL(unicode->str);
- goto onError;
- }
- }
- else {
- unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
- }
- PyObject_INIT(unicode, &PyUnicode_Type);
- }
- else {
- unicode = PyObject_New(PyUnicodeObject, &PyUnicode_Type);
- if (unicode == NULL)
- return NULL;
- unicode->str = PyMem_NEW(Py_UNICODE, length + 1);
- }
-
- if (!unicode->str) {
- PyErr_NoMemory();
- goto onError;
- }
- /* Initialize the first element to guard against cases where
- * the caller fails before initializing str -- unicode_resize()
- * reads str[0], and the Keep-Alive optimization can keep memory
- * allocated for str alive across a call to unicode_dealloc(unicode).
- * We don't want unicode_resize to read uninitialized memory in
- * that case.
- */
- unicode->str[0] = 0;
- unicode->str[length] = 0;
- unicode->length = length;
- unicode->hash = -1;
- unicode->defenc = NULL;
- return unicode;
-
- onError:
- _Py_ForgetReference((PyObject *)unicode);
- PyObject_Del(unicode);
- return NULL;
-}
-
-static
-void unicode_dealloc(register PyUnicodeObject *unicode)
-{
- if (PyUnicode_CheckExact(unicode) &&
- unicode_freelist_size < MAX_UNICODE_FREELIST_SIZE) {
- /* Keep-Alive optimization */
- if (unicode->length >= KEEPALIVE_SIZE_LIMIT) {
- PyMem_DEL(unicode->str);
- unicode->str = NULL;
- unicode->length = 0;
- }
- if (unicode->defenc) {
- Py_DECREF(unicode->defenc);
- unicode->defenc = NULL;
- }
- /* Add to free list */
- *(PyUnicodeObject **)unicode = unicode_freelist;
- unicode_freelist = unicode;
- unicode_freelist_size++;
- }
- else {
- PyMem_DEL(unicode->str);
- Py_XDECREF(unicode->defenc);
- unicode->ob_type->tp_free((PyObject *)unicode);
- }
-}
-
-int PyUnicode_Resize(PyObject **unicode, Py_ssize_t length)
-{
- register PyUnicodeObject *v;
-
- /* Argument checks */
- if (unicode == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
- v = (PyUnicodeObject *)*unicode;
- if (v == NULL || !PyUnicode_Check(v) || v->ob_refcnt != 1 || length < 0) {
- PyErr_BadInternalCall();
- return -1;
- }
-
- /* Resizing unicode_empty and single character objects is not
- possible since these are being shared. We simply return a fresh
- copy with the same Unicode content. */
- if (v->length != length &&
- (v == unicode_empty || v->length == 1)) {
- PyUnicodeObject *w = _PyUnicode_New(length);
- if (w == NULL)
- return -1;
- Py_UNICODE_COPY(w->str, v->str,
- length < v->length ? length : v->length);
- Py_DECREF(*unicode);
- *unicode = (PyObject *)w;
- return 0;
- }
-
- /* Note that we don't have to modify *unicode for unshared Unicode
- objects, since we can modify them in-place. */
- return unicode_resize(v, length);
-}
-
-/* Internal API for use in unicodeobject.c only ! */
-#define _PyUnicode_Resize(unicodevar, length) \
- PyUnicode_Resize(((PyObject **)(unicodevar)), length)
-
-PyObject *PyUnicode_FromUnicode(const Py_UNICODE *u,
- Py_ssize_t size)
-{
- PyUnicodeObject *unicode;
-
- /* If the Unicode data is known at construction time, we can apply
- some optimizations which share commonly used objects. */
- if (u != NULL) {
-
- /* Optimization for empty strings */
- if (size == 0 && unicode_empty != NULL) {
- Py_INCREF(unicode_empty);
- return (PyObject *)unicode_empty;
- }
-
- /* Single character Unicode objects in the Latin-1 range are
- shared when using this constructor */
- if (size == 1 && *u < 256) {
- unicode = unicode_latin1[*u];
- if (!unicode) {
- unicode = _PyUnicode_New(1);
- if (!unicode)
- return NULL;
- unicode->str[0] = *u;
- unicode_latin1[*u] = unicode;
- }
- Py_INCREF(unicode);
- return (PyObject *)unicode;
- }
- }
-
- unicode = _PyUnicode_New(size);
- if (!unicode)
- return NULL;
-
- /* Copy the Unicode data into the new object */
- if (u != NULL)
- Py_UNICODE_COPY(unicode->str, u, size);
-
- return (PyObject *)unicode;
-}
-
-#ifdef HAVE_WCHAR_H
-
-PyObject *PyUnicode_FromWideChar(register const wchar_t *w,
- Py_ssize_t size)
-{
- PyUnicodeObject *unicode;
-
- if (w == NULL) {
- PyErr_BadInternalCall();
- return NULL;
- }
-
- unicode = _PyUnicode_New(size);
- if (!unicode)
- return NULL;
-
- /* Copy the wchar_t data into the new object */
-#ifdef HAVE_USABLE_WCHAR_T
- memcpy(unicode->str, w, size * sizeof(wchar_t));
-#else
- {
- register Py_UNICODE *u;
- register Py_ssize_t i;
- u = PyUnicode_AS_UNICODE(unicode);
- for (i = size; i > 0; i--)
- *u++ = *w++;
- }
-#endif
-
- return (PyObject *)unicode;
-}
-
-Py_ssize_t PyUnicode_AsWideChar(PyUnicodeObject *unicode,
- wchar_t *w,
- Py_ssize_t size)
-{
- if (unicode == NULL) {
- PyErr_BadInternalCall();
- return -1;
- }
-
- /* If possible, try to copy the 0-termination as well */
- if (size > PyUnicode_GET_SIZE(unicode))
- size = PyUnicode_GET_SIZE(unicode) + 1;
-
-#ifdef HAVE_USABLE_WCHAR_T
- memcpy(w, unicode->str, size * sizeof(wchar_t));
-#else
- {
- register Py_UNICODE *u;
- register Py_ssize_t i;
- u = PyUnicode_AS_UNICODE(unicode);
- for (i = size; i > 0; i--)
- *w++ = *u++;
- }
-#endif
-
- if (size > PyUnicode_GET_SIZE(unicode))
- return PyUnicode_GET_SIZE(unicode);
- else
- return size;
-}
-
-#endif
-
-PyObject *PyUnicode_FromOrdinal(int ordinal)
-{
- Py_UNICODE s[1];
-
-#ifdef Py_UNICODE_WIDE
- if (ordinal < 0 || ordinal > 0x10ffff) {
- PyErr_SetString(PyExc_ValueError,
- "unichr() arg not in range(0x110000) "
- "(wide Python build)");
- return NULL;
- }
-#else
- if (ordinal < 0 || ordinal > 0xffff) {
- PyErr_SetString(PyExc_ValueError,
- "unichr() arg not in range(0x10000) "
- "(narrow Python build)");
- return NULL;
- }
-#endif
-
- s[0] = (Py_UNICODE)ordinal;
- return PyUnicode_FromUnicode(s, 1);
-}
-
-PyObject *PyUnicode_FromObject(register PyObject *obj)
-{
- /* XXX Perhaps we should make this API an alias of
- PyObject_Unicode() instead ?! */
- if (PyUnicode_CheckExact(obj)) {
- Py_INCREF(obj);
- return obj;
- }
- if (PyUnicode_Check(obj)) {
- /* For a Unicode subtype that's not a Unicode object,
- return a true Unicode object with the same data. */
- return PyUnicode_FromUnicode(PyUnicode_AS_UNICODE(obj),
- PyUnicode_GET_SIZE(obj));
- }
- return PyUnicode_FromEncodedObject(obj, NULL, "strict");
-}
-
-PyObject *PyUnicode_FromEncodedObject(register PyObject *obj,
- const char *encoding,
- const char *errors)
-{
- const char *s = NULL;
- Py_ssize_t len;
- PyObject *v;
-
- if (obj == NULL) {
- PyErr_BadInternalCall();
- return NULL;
- }
-
-#if 0
- /* For b/w compatibility we also accept Unicode objects provided
- that no encodings is given and then redirect to
- PyObject_Unicode() which then applies the additional logic for
- Unicode subclasses.
-
- NOTE: This API should really only be used for object which
- represent *encoded* Unicode !
-
- */
- if (PyUnicode_Check(obj)) {
- if (encoding) {
- PyErr_SetString(PyExc_TypeError,
- "decoding Unicode is not supported");
- return NULL;
- }
- return PyObject_Unicode(obj);
- }
-#else
- if (PyUnicode_Check(obj)) {
- PyErr_SetString(PyExc_TypeError,
- "decoding Unicode is not supported");
- return NULL;
- }
-#endif
-
- /* Coerce object */
- if (PyString_Check(obj)) {
- s = PyString_AS_STRING(obj);
- len = PyString_GET_SIZE(obj);
- }
- else if (PyObject_AsCharBuffer(obj, &s, &len)) {
- /* Overwrite the error message with something more useful in
- case of a TypeError. */
- if (PyErr_ExceptionMatches(PyExc_TypeError))
- PyErr_Format(PyExc_TypeError,
- "coercing to Unicode: need string or buffer, "
- "%.80s found",
- obj->ob_type->tp_name);
- goto onError;
- }
-
- /* Convert to Unicode */
- if (len == 0) {
- Py_INCREF(unicode_empty);
- v = (PyObject *)unicode_empty;
- }
- else
- v = PyUnicode_Decode(s, len, encoding, errors);
-
- return v;
-
- onError:
- return NULL;
-}
-
-PyObject *PyUnicode_Decode(const char *s,
- Py_ssize_t size,
- const char *encoding,
- const char *errors)
-{
- PyObject *buffer = NULL, *unicode;
-
- if (encoding == NULL)
- encoding = PyUnicode_GetDefaultEncoding();
-
- /* Shortcuts for common default encodings */
- if (strcmp(encoding, "utf-8") == 0)
- return PyUnicode_DecodeUTF8(s, size, errors);
- else if (strcmp(encoding, "latin-1") == 0)
- return PyUnicode_DecodeLatin1(s, size, errors);
-#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
- else if (strcmp(encoding, "mbcs") == 0)
- return PyUnicode_DecodeMBCS(s, size, errors);
-#endif
- else if (strcmp(encoding, "ascii") == 0)
- return PyUnicode_DecodeASCII(s, size, errors);
-
- /* Decode via the codec registry */
- buffer = PyBuffer_FromMemory((void *)s, size);
- if (buffer == NULL)
- goto onError;
- unicode = PyCodec_Decode(buffer, encoding, errors);
- if (unicode == NULL)
- goto onError;
- if (!PyUnicode_Check(unicode)) {
- PyErr_Format(PyExc_TypeError,
- "decoder did not return an unicode object (type=%.400s)",
- unicode->ob_type->tp_name);
- Py_DECREF(unicode);
- goto onError;
- }
- Py_DECREF(buffer);
- return unicode;
-
- onError:
- Py_XDECREF(buffer);
- return NULL;
-}
-
-PyObject *PyUnicode_AsDecodedObject(PyObject *unicode,
- const char *encoding,
- const char *errors)
-{
- PyObject *v;
-
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- goto onError;
- }
-
- if (encoding == NULL)
- encoding = PyUnicode_GetDefaultEncoding();
-
- /* Decode via the codec registry */
- v = PyCodec_Decode(unicode, encoding, errors);
- if (v == NULL)
- goto onError;
- return v;
-
- onError:
- return NULL;
-}
-
-PyObject *PyUnicode_Encode(const Py_UNICODE *s,
- Py_ssize_t size,
- const char *encoding,
- const char *errors)
-{
- PyObject *v, *unicode;
-
- unicode = PyUnicode_FromUnicode(s, size);
- if (unicode == NULL)
- return NULL;
- v = PyUnicode_AsEncodedString(unicode, encoding, errors);
- Py_DECREF(unicode);
- return v;
-}
-
-PyObject *PyUnicode_AsEncodedObject(PyObject *unicode,
- const char *encoding,
- const char *errors)
-{
- PyObject *v;
-
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- goto onError;
- }
-
- if (encoding == NULL)
- encoding = PyUnicode_GetDefaultEncoding();
-
- /* Encode via the codec registry */
- v = PyCodec_Encode(unicode, encoding, errors);
- if (v == NULL)
- goto onError;
- return v;
-
- onError:
- return NULL;
-}
-
-PyObject *PyUnicode_AsEncodedString(PyObject *unicode,
- const char *encoding,
- const char *errors)
-{
- PyObject *v;
-
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- goto onError;
- }
-
- if (encoding == NULL)
- encoding = PyUnicode_GetDefaultEncoding();
-
- /* Shortcuts for common default encodings */
- if (errors == NULL) {
- if (strcmp(encoding, "utf-8") == 0)
- return PyUnicode_AsUTF8String(unicode);
- else if (strcmp(encoding, "latin-1") == 0)
- return PyUnicode_AsLatin1String(unicode);
-#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
- else if (strcmp(encoding, "mbcs") == 0)
- return PyUnicode_AsMBCSString(unicode);
-#endif
- else if (strcmp(encoding, "ascii") == 0)
- return PyUnicode_AsASCIIString(unicode);
- }
-
- /* Encode via the codec registry */
- v = PyCodec_Encode(unicode, encoding, errors);
- if (v == NULL)
- goto onError;
- if (!PyString_Check(v)) {
- PyErr_Format(PyExc_TypeError,
- "encoder did not return a string object (type=%.400s)",
- v->ob_type->tp_name);
- Py_DECREF(v);
- goto onError;
- }
- return v;
-
- onError:
- return NULL;
-}
-
-PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode,
- const char *errors)
-{
- PyObject *v = ((PyUnicodeObject *)unicode)->defenc;
-
- if (v)
- return v;
- v = PyUnicode_AsEncodedString(unicode, NULL, errors);
- if (v && errors == NULL)
- ((PyUnicodeObject *)unicode)->defenc = v;
- return v;
-}
-
-Py_UNICODE *PyUnicode_AsUnicode(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- goto onError;
- }
- return PyUnicode_AS_UNICODE(unicode);
-
- onError:
- return NULL;
-}
-
-Py_ssize_t PyUnicode_GetSize(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- goto onError;
- }
- return PyUnicode_GET_SIZE(unicode);
-
- onError:
- return -1;
-}
-
-const char *PyUnicode_GetDefaultEncoding(void)
-{
- return unicode_default_encoding;
-}
-
-int PyUnicode_SetDefaultEncoding(const char *encoding)
-{
- PyObject *v;
-
- /* Make sure the encoding is valid. As side effect, this also
- loads the encoding into the codec registry cache. */
- v = _PyCodec_Lookup(encoding);
- if (v == NULL)
- goto onError;
- Py_DECREF(v);
- strncpy(unicode_default_encoding,
- encoding,
- sizeof(unicode_default_encoding));
- return 0;
-
- onError:
- return -1;
-}
-
-/* error handling callback helper:
- build arguments, call the callback and check the arguments,
- if no exception occurred, copy the replacement to the output
- and adjust various state variables.
- return 0 on success, -1 on error
-*/
-
-static
-int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler,
- const char *encoding, const char *reason,
- const char *input, Py_ssize_t insize, Py_ssize_t *startinpos, Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr,
- PyObject **output, Py_ssize_t *outpos, Py_UNICODE **outptr)
-{
- static char *argparse = "O!n;decoding error handler must return (unicode, int) tuple";
-
- PyObject *restuple = NULL;
- PyObject *repunicode = NULL;
- Py_ssize_t outsize = PyUnicode_GET_SIZE(*output);
- Py_ssize_t requiredsize;
- Py_ssize_t newpos;
- Py_UNICODE *repptr;
- Py_ssize_t repsize;
- int res = -1;
-
- if (*errorHandler == NULL) {
- *errorHandler = PyCodec_LookupError(errors);
- if (*errorHandler == NULL)
- goto onError;
- }
-
- if (*exceptionObject == NULL) {
- *exceptionObject = PyUnicodeDecodeError_Create(
- encoding, input, insize, *startinpos, *endinpos, reason);
- if (*exceptionObject == NULL)
- goto onError;
- }
- else {
- if (PyUnicodeDecodeError_SetStart(*exceptionObject, *startinpos))
- goto onError;
- if (PyUnicodeDecodeError_SetEnd(*exceptionObject, *endinpos))
- goto onError;
- if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason))
- goto onError;
- }
-
- restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL);
- if (restuple == NULL)
- goto onError;
- if (!PyTuple_Check(restuple)) {
- PyErr_Format(PyExc_TypeError, &argparse[4]);
- goto onError;
- }
- if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos))
- goto onError;
- if (newpos<0)
- newpos = insize+newpos;
- if (newpos<0 || newpos>insize) {
- PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", newpos);
- goto onError;
- }
-
- /* need more space? (at least enough for what we
- have+the replacement+the rest of the string (starting
- at the new input position), so we won't have to check space
- when there are no errors in the rest of the string) */
- repptr = PyUnicode_AS_UNICODE(repunicode);
- repsize = PyUnicode_GET_SIZE(repunicode);
- requiredsize = *outpos + repsize + insize-newpos;
- if (requiredsize > outsize) {
- if (requiredsize<2*outsize)
- requiredsize = 2*outsize;
- if (PyUnicode_Resize(output, requiredsize) < 0)
- goto onError;
- *outptr = PyUnicode_AS_UNICODE(*output) + *outpos;
- }
- *endinpos = newpos;
- *inptr = input + newpos;
- Py_UNICODE_COPY(*outptr, repptr, repsize);
- *outptr += repsize;
- *outpos += repsize;
- /* we made it! */
- res = 0;
-
- onError:
- Py_XDECREF(restuple);
- return res;
-}
-
-/* --- UTF-7 Codec -------------------------------------------------------- */
-
-/* see RFC2152 for details */
-
-static
-char utf7_special[128] = {
- /* indicate whether a UTF-7 character is special i.e. cannot be directly
- encoded:
- 0 - not special
- 1 - special
- 2 - whitespace (optional)
- 3 - RFC2152 Set O (optional) */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0,
- 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3,
- 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1,
-
-};
-
-/* Note: The comparison (c) <= 0 is a trick to work-around gcc
- warnings about the comparison always being false; since
- utf7_special[0] is 1, we can safely make that one comparison
- true */
-
-#define SPECIAL(c, encodeO, encodeWS) \
- ((c) > 127 || (c) <= 0 || utf7_special[(c)] == 1 || \
- (encodeWS && (utf7_special[(c)] == 2)) || \
- (encodeO && (utf7_special[(c)] == 3)))
-
-#define B64(n) \
- ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f])
-#define B64CHAR(c) \
- (isalnum(c) || (c) == '+' || (c) == '/')
-#define UB64(c) \
- ((c) == '+' ? 62 : (c) == '/' ? 63 : (c) >= 'a' ? \
- (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4 )
-
-#define ENCODE(out, ch, bits) \
- while (bits >= 6) { \
- *out++ = B64(ch >> (bits-6)); \
- bits -= 6; \
- }
-
-#define DECODE(out, ch, bits, surrogate) \
- while (bits >= 16) { \
- Py_UNICODE outCh = (Py_UNICODE) ((ch >> (bits-16)) & 0xffff); \
- bits -= 16; \
- if (surrogate) { \
- /* We have already generated an error for the high surrogate \
- so let's not bother seeing if the low surrogate is correct or not */ \
- surrogate = 0; \
- } else if (0xDC00 <= outCh && outCh <= 0xDFFF) { \
- /* This is a surrogate pair. Unfortunately we can't represent \
- it in a 16-bit character */ \
- surrogate = 1; \
- errmsg = "code pairs are not supported"; \
- goto utf7Error; \
- } else { \
- *out++ = outCh; \
- } \
- }
-
-PyObject *PyUnicode_DecodeUTF7(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- const char *e;
- PyUnicodeObject *unicode;
- Py_UNICODE *p;
- const char *errmsg = "";
- int inShift = 0;
- unsigned int bitsleft = 0;
- unsigned long charsleft = 0;
- int surrogate = 0;
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
-
- unicode = _PyUnicode_New(size);
- if (!unicode)
- return NULL;
- if (size == 0)
- return (PyObject *)unicode;
-
- p = unicode->str;
- e = s + size;
-
- while (s < e) {
- Py_UNICODE ch;
- restart:
- ch = *s;
-
- if (inShift) {
- if ((ch == '-') || !B64CHAR(ch)) {
- inShift = 0;
- s++;
-
- /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate);
- if (bitsleft >= 6) {
- /* The shift sequence has a partial character in it. If
- bitsleft < 6 then we could just classify it as padding
- but that is not the case here */
-
- errmsg = "partial character in shift sequence";
- goto utf7Error;
- }
- /* According to RFC2152 the remaining bits should be zero. We
- choose to signal an error/insert a replacement character
- here so indicate the potential of a misencoded character. */
-
- /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */
- if (bitsleft && charsleft << (sizeof(charsleft) * 8 - bitsleft)) {
- errmsg = "non-zero padding bits in shift sequence";
- goto utf7Error;
- }
-
- if (ch == '-') {
- if ((s < e) && (*(s) == '-')) {
- *p++ = '-';
- inShift = 1;
- }
- } else if (SPECIAL(ch,0,0)) {
- errmsg = "unexpected special character";
- goto utf7Error;
- } else {
- *p++ = ch;
- }
- } else {
- charsleft = (charsleft << 6) | UB64(ch);
- bitsleft += 6;
- s++;
- /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate);
- }
- }
- else if ( ch == '+' ) {
- startinpos = s-starts;
- s++;
- if (s < e && *s == '-') {
- s++;
- *p++ = '+';
- } else
- {
- inShift = 1;
- bitsleft = 0;
- }
- }
- else if (SPECIAL(ch,0,0)) {
- errmsg = "unexpected special character";
- s++;
- goto utf7Error;
- }
- else {
- *p++ = ch;
- s++;
- }
- continue;
- utf7Error:
- outpos = p-PyUnicode_AS_UNICODE(unicode);
- endinpos = s-starts;
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "utf7", errmsg,
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&unicode, &outpos, &p))
- goto onError;
- }
-
- if (inShift) {
- outpos = p-PyUnicode_AS_UNICODE(unicode);
- endinpos = size;
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "utf7", "unterminated shift sequence",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&unicode, &outpos, &p))
- goto onError;
- if (s < e)
- goto restart;
- }
-
- if (_PyUnicode_Resize(&unicode, p - PyUnicode_AS_UNICODE(unicode)) < 0)
- goto onError;
-
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)unicode;
-
-onError:
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- Py_DECREF(unicode);
- return NULL;
-}
-
-
-PyObject *PyUnicode_EncodeUTF7(const Py_UNICODE *s,
- Py_ssize_t size,
- int encodeSetO,
- int encodeWhiteSpace,
- const char *errors)
-{
- PyObject *v;
- /* It might be possible to tighten this worst case */
- Py_ssize_t cbAllocated = 5 * size;
- int inShift = 0;
- Py_ssize_t i = 0;
- unsigned int bitsleft = 0;
- unsigned long charsleft = 0;
- char * out;
- char * start;
-
- if (size == 0)
- return PyString_FromStringAndSize(NULL, 0);
-
- v = PyString_FromStringAndSize(NULL, cbAllocated);
- if (v == NULL)
- return NULL;
-
- start = out = PyString_AS_STRING(v);
- for (;i < size; ++i) {
- Py_UNICODE ch = s[i];
-
- if (!inShift) {
- if (ch == '+') {
- *out++ = '+';
- *out++ = '-';
- } else if (SPECIAL(ch, encodeSetO, encodeWhiteSpace)) {
- charsleft = ch;
- bitsleft = 16;
- *out++ = '+';
- /* out, charsleft, bitsleft = */ ENCODE(out, charsleft, bitsleft);
- inShift = bitsleft > 0;
- } else {
- *out++ = (char) ch;
- }
- } else {
- if (!SPECIAL(ch, encodeSetO, encodeWhiteSpace)) {
- *out++ = B64(charsleft << (6-bitsleft));
- charsleft = 0;
- bitsleft = 0;
- /* Characters not in the BASE64 set implicitly unshift the sequence
- so no '-' is required, except if the character is itself a '-' */
- if (B64CHAR(ch) || ch == '-') {
- *out++ = '-';
- }
- inShift = 0;
- *out++ = (char) ch;
- } else {
- bitsleft += 16;
- charsleft = (charsleft << 16) | ch;
- /* out, charsleft, bitsleft = */ ENCODE(out, charsleft, bitsleft);
-
- /* If the next character is special then we dont' need to terminate
- the shift sequence. If the next character is not a BASE64 character
- or '-' then the shift sequence will be terminated implicitly and we
- don't have to insert a '-'. */
-
- if (bitsleft == 0) {
- if (i + 1 < size) {
- Py_UNICODE ch2 = s[i+1];
-
- if (SPECIAL(ch2, encodeSetO, encodeWhiteSpace)) {
-
- } else if (B64CHAR(ch2) || ch2 == '-') {
- *out++ = '-';
- inShift = 0;
- } else {
- inShift = 0;
- }
-
- }
- else {
- *out++ = '-';
- inShift = 0;
- }
- }
- }
- }
- }
- if (bitsleft) {
- *out++= B64(charsleft << (6-bitsleft) );
- *out++ = '-';
- }
-
- _PyString_Resize(&v, out - start);
- return v;
-}
-
-#undef SPECIAL
-#undef B64
-#undef B64CHAR
-#undef UB64
-#undef ENCODE
-#undef DECODE
-
-/* --- UTF-8 Codec -------------------------------------------------------- */
-
-static
-char utf8_code_length[256] = {
- /* Map UTF-8 encoded prefix byte to sequence length. zero means
- illegal prefix. see RFC 2279 for details */
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 0, 0
-};
-
-PyObject *PyUnicode_DecodeUTF8(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- return PyUnicode_DecodeUTF8Stateful(s, size, errors, NULL);
-}
-
-PyObject *PyUnicode_DecodeUTF8Stateful(const char *s,
- Py_ssize_t size,
- const char *errors,
- Py_ssize_t *consumed)
-{
- const char *starts = s;
- int n;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- const char *e;
- PyUnicodeObject *unicode;
- Py_UNICODE *p;
- const char *errmsg = "";
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
-
- /* Note: size will always be longer than the resulting Unicode
- character count */
- unicode = _PyUnicode_New(size);
- if (!unicode)
- return NULL;
- if (size == 0) {
- if (consumed)
- *consumed = 0;
- return (PyObject *)unicode;
- }
-
- /* Unpack UTF-8 encoded data */
- p = unicode->str;
- e = s + size;
-
- while (s < e) {
- Py_UCS4 ch = (unsigned char)*s;
-
- if (ch < 0x80) {
- *p++ = (Py_UNICODE)ch;
- s++;
- continue;
- }
-
- n = utf8_code_length[ch];
-
- if (s + n > e) {
- if (consumed)
- break;
- else {
- errmsg = "unexpected end of data";
- startinpos = s-starts;
- endinpos = size;
- goto utf8Error;
- }
- }
-
- switch (n) {
-
- case 0:
- errmsg = "unexpected code byte";
- startinpos = s-starts;
- endinpos = startinpos+1;
- goto utf8Error;
-
- case 1:
- errmsg = "internal error";
- startinpos = s-starts;
- endinpos = startinpos+1;
- goto utf8Error;
-
- case 2:
- if ((s[1] & 0xc0) != 0x80) {
- errmsg = "invalid data";
- startinpos = s-starts;
- endinpos = startinpos+2;
- goto utf8Error;
- }
- ch = ((s[0] & 0x1f) << 6) + (s[1] & 0x3f);
- if (ch < 0x80) {
- startinpos = s-starts;
- endinpos = startinpos+2;
- errmsg = "illegal encoding";
- goto utf8Error;
- }
- else
- *p++ = (Py_UNICODE)ch;
- break;
-
- case 3:
- if ((s[1] & 0xc0) != 0x80 ||
- (s[2] & 0xc0) != 0x80) {
- errmsg = "invalid data";
- startinpos = s-starts;
- endinpos = startinpos+3;
- goto utf8Error;
- }
- ch = ((s[0] & 0x0f) << 12) + ((s[1] & 0x3f) << 6) + (s[2] & 0x3f);
- if (ch < 0x0800) {
- /* Note: UTF-8 encodings of surrogates are considered
- legal UTF-8 sequences;
-
- XXX For wide builds (UCS-4) we should probably try
- to recombine the surrogates into a single code
- unit.
- */
- errmsg = "illegal encoding";
- startinpos = s-starts;
- endinpos = startinpos+3;
- goto utf8Error;
- }
- else
- *p++ = (Py_UNICODE)ch;
- break;
-
- case 4:
- if ((s[1] & 0xc0) != 0x80 ||
- (s[2] & 0xc0) != 0x80 ||
- (s[3] & 0xc0) != 0x80) {
- errmsg = "invalid data";
- startinpos = s-starts;
- endinpos = startinpos+4;
- goto utf8Error;
- }
- ch = ((s[0] & 0x7) << 18) + ((s[1] & 0x3f) << 12) +
- ((s[2] & 0x3f) << 6) + (s[3] & 0x3f);
- /* validate and convert to UTF-16 */
- if ((ch < 0x10000) /* minimum value allowed for 4
- byte encoding */
- || (ch > 0x10ffff)) /* maximum value allowed for
- UTF-16 */
- {
- errmsg = "illegal encoding";
- startinpos = s-starts;
- endinpos = startinpos+4;
- goto utf8Error;
- }
-#ifdef Py_UNICODE_WIDE
- *p++ = (Py_UNICODE)ch;
-#else
- /* compute and append the two surrogates: */
-
- /* translate from 10000..10FFFF to 0..FFFF */
- ch -= 0x10000;
-
- /* high surrogate = top 10 bits added to D800 */
- *p++ = (Py_UNICODE)(0xD800 + (ch >> 10));
-
- /* low surrogate = bottom 10 bits added to DC00 */
- *p++ = (Py_UNICODE)(0xDC00 + (ch & 0x03FF));
-#endif
- break;
-
- default:
- /* Other sizes are only needed for UCS-4 */
- errmsg = "unsupported Unicode code range";
- startinpos = s-starts;
- endinpos = startinpos+n;
- goto utf8Error;
- }
- s += n;
- continue;
-
- utf8Error:
- outpos = p-PyUnicode_AS_UNICODE(unicode);
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "utf8", errmsg,
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&unicode, &outpos, &p))
- goto onError;
- }
- if (consumed)
- *consumed = s-starts;
-
- /* Adjust length */
- if (_PyUnicode_Resize(&unicode, p - unicode->str) < 0)
- goto onError;
-
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)unicode;
-
-onError:
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- Py_DECREF(unicode);
- return NULL;
-}
-
-/* Allocation strategy: if the string is short, convert into a stack buffer
- and allocate exactly as much space needed at the end. Else allocate the
- maximum possible needed (4 result bytes per Unicode character), and return
- the excess memory at the end.
-*/
-PyObject *
-PyUnicode_EncodeUTF8(const Py_UNICODE *s,
- Py_ssize_t size,
- const char *errors)
-{
-#define MAX_SHORT_UNICHARS 300 /* largest size we'll do on the stack */
-
- Py_ssize_t i; /* index into s of next input byte */
- PyObject *v; /* result string object */
- char *p; /* next free byte in output buffer */
- Py_ssize_t nallocated; /* number of result bytes allocated */
- Py_ssize_t nneeded; /* number of result bytes needed */
- char stackbuf[MAX_SHORT_UNICHARS * 4];
-
- assert(s != NULL);
- assert(size >= 0);
-
- if (size <= MAX_SHORT_UNICHARS) {
- /* Write into the stack buffer; nallocated can't overflow.
- * At the end, we'll allocate exactly as much heap space as it
- * turns out we need.
- */
- nallocated = Py_SAFE_DOWNCAST(sizeof(stackbuf), size_t, int);
- v = NULL; /* will allocate after we're done */
- p = stackbuf;
- }
- else {
- /* Overallocate on the heap, and give the excess back at the end. */
- nallocated = size * 4;
- if (nallocated / 4 != size) /* overflow! */
- return PyErr_NoMemory();
- v = PyString_FromStringAndSize(NULL, nallocated);
- if (v == NULL)
- return NULL;
- p = PyString_AS_STRING(v);
- }
-
- for (i = 0; i < size;) {
- Py_UCS4 ch = s[i++];
-
- if (ch < 0x80)
- /* Encode ASCII */
- *p++ = (char) ch;
-
- else if (ch < 0x0800) {
- /* Encode Latin-1 */
- *p++ = (char)(0xc0 | (ch >> 6));
- *p++ = (char)(0x80 | (ch & 0x3f));
- }
- else {
- /* Encode UCS2 Unicode ordinals */
- if (ch < 0x10000) {
- /* Special case: check for high surrogate */
- if (0xD800 <= ch && ch <= 0xDBFF && i != size) {
- Py_UCS4 ch2 = s[i];
- /* Check for low surrogate and combine the two to
- form a UCS4 value */
- if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
- ch = ((ch - 0xD800) << 10 | (ch2 - 0xDC00)) + 0x10000;
- i++;
- goto encodeUCS4;
- }
- /* Fall through: handles isolated high surrogates */
- }
- *p++ = (char)(0xe0 | (ch >> 12));
- *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
- *p++ = (char)(0x80 | (ch & 0x3f));
- continue;
- }
-encodeUCS4:
- /* Encode UCS4 Unicode ordinals */
- *p++ = (char)(0xf0 | (ch >> 18));
- *p++ = (char)(0x80 | ((ch >> 12) & 0x3f));
- *p++ = (char)(0x80 | ((ch >> 6) & 0x3f));
- *p++ = (char)(0x80 | (ch & 0x3f));
- }
- }
-
- if (v == NULL) {
- /* This was stack allocated. */
- nneeded = p - stackbuf;
- assert(nneeded <= nallocated);
- v = PyString_FromStringAndSize(stackbuf, nneeded);
- }
- else {
- /* Cut back to size actually needed. */
- nneeded = p - PyString_AS_STRING(v);
- assert(nneeded <= nallocated);
- _PyString_Resize(&v, nneeded);
- }
- return v;
-
-#undef MAX_SHORT_UNICHARS
-}
-
-PyObject *PyUnicode_AsUTF8String(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeUTF8(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode),
- NULL);
-}
-
-/* --- UTF-16 Codec ------------------------------------------------------- */
-
-PyObject *
-PyUnicode_DecodeUTF16(const char *s,
- Py_ssize_t size,
- const char *errors,
- int *byteorder)
-{
- return PyUnicode_DecodeUTF16Stateful(s, size, errors, byteorder, NULL);
-}
-
-PyObject *
-PyUnicode_DecodeUTF16Stateful(const char *s,
- Py_ssize_t size,
- const char *errors,
- int *byteorder,
- Py_ssize_t *consumed)
-{
- const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- PyUnicodeObject *unicode;
- Py_UNICODE *p;
- const unsigned char *q, *e;
- int bo = 0; /* assume native ordering by default */
- const char *errmsg = "";
- /* Offsets from q for retrieving byte pairs in the right order. */
-#ifdef BYTEORDER_IS_LITTLE_ENDIAN
- int ihi = 1, ilo = 0;
-#else
- int ihi = 0, ilo = 1;
-#endif
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
-
- /* Note: size will always be longer than the resulting Unicode
- character count */
- unicode = _PyUnicode_New(size);
- if (!unicode)
- return NULL;
- if (size == 0)
- return (PyObject *)unicode;
-
- /* Unpack UTF-16 encoded data */
- p = unicode->str;
- q = (unsigned char *)s;
- e = q + size;
-
- if (byteorder)
- bo = *byteorder;
-
- /* Check for BOM marks (U+FEFF) in the input and adjust current
- byte order setting accordingly. In native mode, the leading BOM
- mark is skipped, in all other modes, it is copied to the output
- stream as-is (giving a ZWNBSP character). */
- if (bo == 0) {
- if (size >= 2) {
- const Py_UNICODE bom = (q[ihi] << 8) | q[ilo];
-#ifdef BYTEORDER_IS_LITTLE_ENDIAN
- if (bom == 0xFEFF) {
- q += 2;
- bo = -1;
- }
- else if (bom == 0xFFFE) {
- q += 2;
- bo = 1;
- }
-#else
- if (bom == 0xFEFF) {
- q += 2;
- bo = 1;
- }
- else if (bom == 0xFFFE) {
- q += 2;
- bo = -1;
- }
-#endif
- }
- }
-
- if (bo == -1) {
- /* force LE */
- ihi = 1;
- ilo = 0;
- }
- else if (bo == 1) {
- /* force BE */
- ihi = 0;
- ilo = 1;
- }
-
- while (q < e) {
- Py_UNICODE ch;
- /* remaining bytes at the end? (size should be even) */
- if (e-q<2) {
- if (consumed)
- break;
- errmsg = "truncated data";
- startinpos = ((const char *)q)-starts;
- endinpos = ((const char *)e)-starts;
- goto utf16Error;
- /* The remaining input chars are ignored if the callback
- chooses to skip the input */
- }
- ch = (q[ihi] << 8) | q[ilo];
-
- q += 2;
-
- if (ch < 0xD800 || ch > 0xDFFF) {
- *p++ = ch;
- continue;
- }
-
- /* UTF-16 code pair: */
- if (q >= e) {
- errmsg = "unexpected end of data";
- startinpos = (((const char *)q)-2)-starts;
- endinpos = ((const char *)e)-starts;
- goto utf16Error;
- }
- if (0xD800 <= ch && ch <= 0xDBFF) {
- Py_UNICODE ch2 = (q[ihi] << 8) | q[ilo];
- q += 2;
- if (0xDC00 <= ch2 && ch2 <= 0xDFFF) {
-#ifndef Py_UNICODE_WIDE
- *p++ = ch;
- *p++ = ch2;
-#else
- *p++ = (((ch & 0x3FF)<<10) | (ch2 & 0x3FF)) + 0x10000;
-#endif
- continue;
- }
- else {
- errmsg = "illegal UTF-16 surrogate";
- startinpos = (((const char *)q)-4)-starts;
- endinpos = startinpos+2;
- goto utf16Error;
- }
-
- }
- errmsg = "illegal encoding";
- startinpos = (((const char *)q)-2)-starts;
- endinpos = startinpos+2;
- /* Fall through to report the error */
-
- utf16Error:
- outpos = p-PyUnicode_AS_UNICODE(unicode);
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "utf16", errmsg,
- starts, size, &startinpos, &endinpos, &exc, (const char **)&q,
- (PyObject **)&unicode, &outpos, &p))
- goto onError;
- }
-
- if (byteorder)
- *byteorder = bo;
-
- if (consumed)
- *consumed = (const char *)q-starts;
-
- /* Adjust length */
- if (_PyUnicode_Resize(&unicode, p - unicode->str) < 0)
- goto onError;
-
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)unicode;
-
-onError:
- Py_DECREF(unicode);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-}
-
-PyObject *
-PyUnicode_EncodeUTF16(const Py_UNICODE *s,
- Py_ssize_t size,
- const char *errors,
- int byteorder)
-{
- PyObject *v;
- unsigned char *p;
-#ifdef Py_UNICODE_WIDE
- int i, pairs;
-#else
- const int pairs = 0;
-#endif
- /* Offsets from p for storing byte pairs in the right order. */
-#ifdef BYTEORDER_IS_LITTLE_ENDIAN
- int ihi = 1, ilo = 0;
-#else
- int ihi = 0, ilo = 1;
-#endif
-
-#define STORECHAR(CH) \
- do { \
- p[ihi] = ((CH) >> 8) & 0xff; \
- p[ilo] = (CH) & 0xff; \
- p += 2; \
- } while(0)
-
-#ifdef Py_UNICODE_WIDE
- for (i = pairs = 0; i < size; i++)
- if (s[i] >= 0x10000)
- pairs++;
-#endif
- v = PyString_FromStringAndSize(NULL,
- 2 * (size + pairs + (byteorder == 0)));
- if (v == NULL)
- return NULL;
-
- p = (unsigned char *)PyString_AS_STRING(v);
- if (byteorder == 0)
- STORECHAR(0xFEFF);
- if (size == 0)
- return v;
-
- if (byteorder == -1) {
- /* force LE */
- ihi = 1;
- ilo = 0;
- }
- else if (byteorder == 1) {
- /* force BE */
- ihi = 0;
- ilo = 1;
- }
-
- while (size-- > 0) {
- Py_UNICODE ch = *s++;
- Py_UNICODE ch2 = 0;
-#ifdef Py_UNICODE_WIDE
- if (ch >= 0x10000) {
- ch2 = 0xDC00 | ((ch-0x10000) & 0x3FF);
- ch = 0xD800 | ((ch-0x10000) >> 10);
- }
-#endif
- STORECHAR(ch);
- if (ch2)
- STORECHAR(ch2);
- }
- return v;
-#undef STORECHAR
-}
-
-PyObject *PyUnicode_AsUTF16String(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeUTF16(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode),
- NULL,
- 0);
-}
-
-/* --- Unicode Escape Codec ----------------------------------------------- */
-
-static _PyUnicode_Name_CAPI *ucnhash_CAPI = NULL;
-
-PyObject *PyUnicode_DecodeUnicodeEscape(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- int i;
- PyUnicodeObject *v;
- Py_UNICODE *p;
- const char *end;
- char* message;
- Py_UCS4 chr = 0xffffffff; /* in case 'getcode' messes up */
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
-
- /* Escaped strings will always be longer than the resulting
- Unicode string, so we start with size here and then reduce the
- length after conversion to the true value.
- (but if the error callback returns a long replacement string
- we'll have to allocate more space) */
- v = _PyUnicode_New(size);
- if (v == NULL)
- goto onError;
- if (size == 0)
- return (PyObject *)v;
-
- p = PyUnicode_AS_UNICODE(v);
- end = s + size;
-
- while (s < end) {
- unsigned char c;
- Py_UNICODE x;
- int digits;
-
- /* Non-escape characters are interpreted as Unicode ordinals */
- if (*s != '\\') {
- *p++ = (unsigned char) *s++;
- continue;
- }
-
- startinpos = s-starts;
- /* \ - Escapes */
- s++;
- switch (*s++) {
-
- /* \x escapes */
- case '\n': break;
- case '\\': *p++ = '\\'; break;
- case '\'': *p++ = '\''; break;
- case '\"': *p++ = '\"'; break;
- case 'b': *p++ = '\b'; break;
- case 'f': *p++ = '\014'; break; /* FF */
- case 't': *p++ = '\t'; break;
- case 'n': *p++ = '\n'; break;
- case 'r': *p++ = '\r'; break;
- case 'v': *p++ = '\013'; break; /* VT */
- case 'a': *p++ = '\007'; break; /* BEL, not classic C */
-
- /* \OOO (octal) escapes */
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- x = s[-1] - '0';
- if ('0' <= *s && *s <= '7') {
- x = (x<<3) + *s++ - '0';
- if ('0' <= *s && *s <= '7')
- x = (x<<3) + *s++ - '0';
- }
- *p++ = x;
- break;
-
- /* hex escapes */
- /* \xXX */
- case 'x':
- digits = 2;
- message = "truncated \\xXX escape";
- goto hexescape;
-
- /* \uXXXX */
- case 'u':
- digits = 4;
- message = "truncated \\uXXXX escape";
- goto hexescape;
-
- /* \UXXXXXXXX */
- case 'U':
- digits = 8;
- message = "truncated \\UXXXXXXXX escape";
- hexescape:
- chr = 0;
- outpos = p-PyUnicode_AS_UNICODE(v);
- if (s+digits>end) {
- endinpos = size;
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "unicodeescape", "end of string in escape sequence",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- goto nextByte;
- }
- for (i = 0; i < digits; ++i) {
- c = (unsigned char) s[i];
- if (!isxdigit(c)) {
- endinpos = (s+i+1)-starts;
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "unicodeescape", message,
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- goto nextByte;
- }
- chr = (chr<<4) & ~0xF;
- if (c >= '0' && c <= '9')
- chr += c - '0';
- else if (c >= 'a' && c <= 'f')
- chr += 10 + c - 'a';
- else
- chr += 10 + c - 'A';
- }
- s += i;
- if (chr == 0xffffffff && PyErr_Occurred())
- /* _decoding_error will have already written into the
- target buffer. */
- break;
- store:
- /* when we get here, chr is a 32-bit unicode character */
- if (chr <= 0xffff)
- /* UCS-2 character */
- *p++ = (Py_UNICODE) chr;
- else if (chr <= 0x10ffff) {
- /* UCS-4 character. Either store directly, or as
- surrogate pair. */
-#ifdef Py_UNICODE_WIDE
- *p++ = chr;
-#else
- chr -= 0x10000L;
- *p++ = 0xD800 + (Py_UNICODE) (chr >> 10);
- *p++ = 0xDC00 + (Py_UNICODE) (chr & 0x03FF);
-#endif
- } else {
- endinpos = s-starts;
- outpos = p-PyUnicode_AS_UNICODE(v);
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "unicodeescape", "illegal Unicode character",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- }
- break;
-
- /* \N{name} */
- case 'N':
- message = "malformed \\N character escape";
- if (ucnhash_CAPI == NULL) {
- /* load the unicode data module */
- PyObject *m, *api;
- m = PyImport_ImportModule("unicodedata");
- if (m == NULL)
- goto ucnhashError;
- api = PyObject_GetAttrString(m, "ucnhash_CAPI");
- Py_DECREF(m);
- if (api == NULL)
- goto ucnhashError;
- ucnhash_CAPI = (_PyUnicode_Name_CAPI *)PyCObject_AsVoidPtr(api);
- Py_DECREF(api);
- if (ucnhash_CAPI == NULL)
- goto ucnhashError;
- }
- if (*s == '{') {
- const char *start = s+1;
- /* look for the closing brace */
- while (*s != '}' && s < end)
- s++;
- if (s > start && s < end && *s == '}') {
- /* found a name. look it up in the unicode database */
- message = "unknown Unicode character name";
- s++;
- if (ucnhash_CAPI->getcode(NULL, start, (int)(s-start-1), &chr))
- goto store;
- }
- }
- endinpos = s-starts;
- outpos = p-PyUnicode_AS_UNICODE(v);
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "unicodeescape", message,
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- break;
-
- default:
- if (s > end) {
- message = "\\ at end of string";
- s--;
- endinpos = s-starts;
- outpos = p-PyUnicode_AS_UNICODE(v);
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "unicodeescape", message,
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- }
- else {
- *p++ = '\\';
- *p++ = (unsigned char)s[-1];
- }
- break;
- }
- nextByte:
- ;
- }
- if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)
- goto onError;
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)v;
-
-ucnhashError:
- PyErr_SetString(
- PyExc_UnicodeError,
- "\\N escapes not supported (can't load unicodedata module)"
- );
- Py_XDECREF(v);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-
-onError:
- Py_XDECREF(v);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-}
-
-/* Return a Unicode-Escape string version of the Unicode object.
-
- If quotes is true, the string is enclosed in u"" or u'' quotes as
- appropriate.
-
-*/
-
-Py_LOCAL_INLINE(const Py_UNICODE *) findchar(const Py_UNICODE *s,
- Py_ssize_t size,
- Py_UNICODE ch)
-{
- /* like wcschr, but doesn't stop at NULL characters */
-
- while (size-- > 0) {
- if (*s == ch)
- return s;
- s++;
- }
-
- return NULL;
-}
-
-static
-PyObject *unicodeescape_string(const Py_UNICODE *s,
- Py_ssize_t size,
- int quotes)
-{
- PyObject *repr;
- char *p;
-
- static const char *hexdigit = "0123456789abcdef";
-
- /* Initial allocation is based on the longest-possible unichr
- escape.
-
- In wide (UTF-32) builds '\U00xxxxxx' is 10 chars per source
- unichr, so in this case it's the longest unichr escape. In
- narrow (UTF-16) builds this is five chars per source unichr
- since there are two unichrs in the surrogate pair, so in narrow
- (UTF-16) builds it's not the longest unichr escape.
-
- In wide or narrow builds '\uxxxx' is 6 chars per source unichr,
- so in the narrow (UTF-16) build case it's the longest unichr
- escape.
- */
-
- repr = PyString_FromStringAndSize(NULL,
- 2
-#ifdef Py_UNICODE_WIDE
- + 10*size
-#else
- + 6*size
-#endif
- + 1);
- if (repr == NULL)
- return NULL;
-
- p = PyString_AS_STRING(repr);
-
- if (quotes) {
- *p++ = 'u';
- *p++ = (findchar(s, size, '\'') &&
- !findchar(s, size, '"')) ? '"' : '\'';
- }
- while (size-- > 0) {
- Py_UNICODE ch = *s++;
-
- /* Escape quotes and backslashes */
- if ((quotes &&
- ch == (Py_UNICODE) PyString_AS_STRING(repr)[1]) || ch == '\\') {
- *p++ = '\\';
- *p++ = (char) ch;
- continue;
- }
-
-#ifdef Py_UNICODE_WIDE
- /* Map 21-bit characters to '\U00xxxxxx' */
- else if (ch >= 0x10000) {
- *p++ = '\\';
- *p++ = 'U';
- *p++ = hexdigit[(ch >> 28) & 0x0000000F];
- *p++ = hexdigit[(ch >> 24) & 0x0000000F];
- *p++ = hexdigit[(ch >> 20) & 0x0000000F];
- *p++ = hexdigit[(ch >> 16) & 0x0000000F];
- *p++ = hexdigit[(ch >> 12) & 0x0000000F];
- *p++ = hexdigit[(ch >> 8) & 0x0000000F];
- *p++ = hexdigit[(ch >> 4) & 0x0000000F];
- *p++ = hexdigit[ch & 0x0000000F];
- continue;
- }
-#else
- /* Map UTF-16 surrogate pairs to '\U00xxxxxx' */
- else if (ch >= 0xD800 && ch < 0xDC00) {
- Py_UNICODE ch2;
- Py_UCS4 ucs;
-
- ch2 = *s++;
- size--;
- if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) {
- ucs = (((ch & 0x03FF) << 10) | (ch2 & 0x03FF)) + 0x00010000;
- *p++ = '\\';
- *p++ = 'U';
- *p++ = hexdigit[(ucs >> 28) & 0x0000000F];
- *p++ = hexdigit[(ucs >> 24) & 0x0000000F];
- *p++ = hexdigit[(ucs >> 20) & 0x0000000F];
- *p++ = hexdigit[(ucs >> 16) & 0x0000000F];
- *p++ = hexdigit[(ucs >> 12) & 0x0000000F];
- *p++ = hexdigit[(ucs >> 8) & 0x0000000F];
- *p++ = hexdigit[(ucs >> 4) & 0x0000000F];
- *p++ = hexdigit[ucs & 0x0000000F];
- continue;
- }
- /* Fall through: isolated surrogates are copied as-is */
- s--;
- size++;
- }
-#endif
-
- /* Map 16-bit characters to '\uxxxx' */
- if (ch >= 256) {
- *p++ = '\\';
- *p++ = 'u';
- *p++ = hexdigit[(ch >> 12) & 0x000F];
- *p++ = hexdigit[(ch >> 8) & 0x000F];
- *p++ = hexdigit[(ch >> 4) & 0x000F];
- *p++ = hexdigit[ch & 0x000F];
- }
-
- /* Map special whitespace to '\t', \n', '\r' */
- else if (ch == '\t') {
- *p++ = '\\';
- *p++ = 't';
- }
- else if (ch == '\n') {
- *p++ = '\\';
- *p++ = 'n';
- }
- else if (ch == '\r') {
- *p++ = '\\';
- *p++ = 'r';
- }
-
- /* Map non-printable US ASCII to '\xhh' */
- else if (ch < ' ' || ch >= 0x7F) {
- *p++ = '\\';
- *p++ = 'x';
- *p++ = hexdigit[(ch >> 4) & 0x000F];
- *p++ = hexdigit[ch & 0x000F];
- }
-
- /* Copy everything else as-is */
- else
- *p++ = (char) ch;
- }
- if (quotes)
- *p++ = PyString_AS_STRING(repr)[1];
-
- *p = '\0';
- _PyString_Resize(&repr, p - PyString_AS_STRING(repr));
- return repr;
-}
-
-PyObject *PyUnicode_EncodeUnicodeEscape(const Py_UNICODE *s,
- Py_ssize_t size)
-{
- return unicodeescape_string(s, size, 0);
-}
-
-PyObject *PyUnicode_AsUnicodeEscapeString(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeUnicodeEscape(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode));
-}
-
-/* --- Raw Unicode Escape Codec ------------------------------------------- */
-
-PyObject *PyUnicode_DecodeRawUnicodeEscape(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- PyUnicodeObject *v;
- Py_UNICODE *p;
- const char *end;
- const char *bs;
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
-
- /* Escaped strings will always be longer than the resulting
- Unicode string, so we start with size here and then reduce the
- length after conversion to the true value. (But decoding error
- handler might have to resize the string) */
- v = _PyUnicode_New(size);
- if (v == NULL)
- goto onError;
- if (size == 0)
- return (PyObject *)v;
- p = PyUnicode_AS_UNICODE(v);
- end = s + size;
- while (s < end) {
- unsigned char c;
- Py_UCS4 x;
- int i;
- int count;
-
- /* Non-escape characters are interpreted as Unicode ordinals */
- if (*s != '\\') {
- *p++ = (unsigned char)*s++;
- continue;
- }
- startinpos = s-starts;
-
- /* \u-escapes are only interpreted iff the number of leading
- backslashes if odd */
- bs = s;
- for (;s < end;) {
- if (*s != '\\')
- break;
- *p++ = (unsigned char)*s++;
- }
- if (((s - bs) & 1) == 0 ||
- s >= end ||
- (*s != 'u' && *s != 'U')) {
- continue;
- }
- p--;
- count = *s=='u' ? 4 : 8;
- s++;
-
- /* \uXXXX with 4 hex digits, \Uxxxxxxxx with 8 */
- outpos = p-PyUnicode_AS_UNICODE(v);
- for (x = 0, i = 0; i < count; ++i, ++s) {
- c = (unsigned char)*s;
- if (!isxdigit(c)) {
- endinpos = s-starts;
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "rawunicodeescape", "truncated \\uXXXX",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- goto nextByte;
- }
- x = (x<<4) & ~0xF;
- if (c >= '0' && c <= '9')
- x += c - '0';
- else if (c >= 'a' && c <= 'f')
- x += 10 + c - 'a';
- else
- x += 10 + c - 'A';
- }
-#ifndef Py_UNICODE_WIDE
- if (x > 0x10000) {
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "rawunicodeescape", "\\Uxxxxxxxx out of range",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- }
-#endif
- *p++ = x;
- nextByte:
- ;
- }
- if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)
- goto onError;
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)v;
-
- onError:
- Py_XDECREF(v);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-}
-
-PyObject *PyUnicode_EncodeRawUnicodeEscape(const Py_UNICODE *s,
- Py_ssize_t size)
-{
- PyObject *repr;
- char *p;
- char *q;
-
- static const char *hexdigit = "0123456789abcdef";
-
-#ifdef Py_UNICODE_WIDE
- repr = PyString_FromStringAndSize(NULL, 10 * size);
-#else
- repr = PyString_FromStringAndSize(NULL, 6 * size);
-#endif
- if (repr == NULL)
- return NULL;
- if (size == 0)
- return repr;
-
- p = q = PyString_AS_STRING(repr);
- while (size-- > 0) {
- Py_UNICODE ch = *s++;
-#ifdef Py_UNICODE_WIDE
- /* Map 32-bit characters to '\Uxxxxxxxx' */
- if (ch >= 0x10000) {
- *p++ = '\\';
- *p++ = 'U';
- *p++ = hexdigit[(ch >> 28) & 0xf];
- *p++ = hexdigit[(ch >> 24) & 0xf];
- *p++ = hexdigit[(ch >> 20) & 0xf];
- *p++ = hexdigit[(ch >> 16) & 0xf];
- *p++ = hexdigit[(ch >> 12) & 0xf];
- *p++ = hexdigit[(ch >> 8) & 0xf];
- *p++ = hexdigit[(ch >> 4) & 0xf];
- *p++ = hexdigit[ch & 15];
- }
- else
-#endif
- /* Map 16-bit characters to '\uxxxx' */
- if (ch >= 256) {
- *p++ = '\\';
- *p++ = 'u';
- *p++ = hexdigit[(ch >> 12) & 0xf];
- *p++ = hexdigit[(ch >> 8) & 0xf];
- *p++ = hexdigit[(ch >> 4) & 0xf];
- *p++ = hexdigit[ch & 15];
- }
- /* Copy everything else as-is */
- else
- *p++ = (char) ch;
- }
- *p = '\0';
- _PyString_Resize(&repr, p - q);
- return repr;
-}
-
-PyObject *PyUnicode_AsRawUnicodeEscapeString(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeRawUnicodeEscape(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode));
-}
-
-/* --- Unicode Internal Codec ------------------------------------------- */
-
-PyObject *_PyUnicode_DecodeUnicodeInternal(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- PyUnicodeObject *v;
- Py_UNICODE *p;
- const char *end;
- const char *reason;
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
-
-#ifdef Py_UNICODE_WIDE
- Py_UNICODE unimax = PyUnicode_GetMax();
-#endif
-
- /* XXX overflow detection missing */
- v = _PyUnicode_New((size+Py_UNICODE_SIZE-1)/ Py_UNICODE_SIZE);
- if (v == NULL)
- goto onError;
- if (PyUnicode_GetSize((PyObject *)v) == 0)
- return (PyObject *)v;
- p = PyUnicode_AS_UNICODE(v);
- end = s + size;
-
- while (s < end) {
- memcpy(p, s, sizeof(Py_UNICODE));
- /* We have to sanity check the raw data, otherwise doom looms for
- some malformed UCS-4 data. */
- if (
- #ifdef Py_UNICODE_WIDE
- *p > unimax || *p < 0 ||
- #endif
- end-s < Py_UNICODE_SIZE
- )
- {
- startinpos = s - starts;
- if (end-s < Py_UNICODE_SIZE) {
- endinpos = end-starts;
- reason = "truncated input";
- }
- else {
- endinpos = s - starts + Py_UNICODE_SIZE;
- reason = "illegal code point (> 0x10FFFF)";
- }
- outpos = p - PyUnicode_AS_UNICODE(v);
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "unicode_internal", reason,
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p)) {
- goto onError;
- }
- }
- else {
- p++;
- s += Py_UNICODE_SIZE;
- }
- }
-
- if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)
- goto onError;
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)v;
-
- onError:
- Py_XDECREF(v);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-}
-
-/* --- Latin-1 Codec ------------------------------------------------------ */
-
-PyObject *PyUnicode_DecodeLatin1(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- PyUnicodeObject *v;
- Py_UNICODE *p;
-
- /* Latin-1 is equivalent to the first 256 ordinals in Unicode. */
- if (size == 1) {
- Py_UNICODE r = *(unsigned char*)s;
- return PyUnicode_FromUnicode(&r, 1);
- }
-
- v = _PyUnicode_New(size);
- if (v == NULL)
- goto onError;
- if (size == 0)
- return (PyObject *)v;
- p = PyUnicode_AS_UNICODE(v);
- while (size-- > 0)
- *p++ = (unsigned char)*s++;
- return (PyObject *)v;
-
- onError:
- Py_XDECREF(v);
- return NULL;
-}
-
-/* create or adjust a UnicodeEncodeError */
-static void make_encode_exception(PyObject **exceptionObject,
- const char *encoding,
- const Py_UNICODE *unicode, Py_ssize_t size,
- Py_ssize_t startpos, Py_ssize_t endpos,
- const char *reason)
-{
- if (*exceptionObject == NULL) {
- *exceptionObject = PyUnicodeEncodeError_Create(
- encoding, unicode, size, startpos, endpos, reason);
- }
- else {
- if (PyUnicodeEncodeError_SetStart(*exceptionObject, startpos))
- goto onError;
- if (PyUnicodeEncodeError_SetEnd(*exceptionObject, endpos))
- goto onError;
- if (PyUnicodeEncodeError_SetReason(*exceptionObject, reason))
- goto onError;
- return;
- onError:
- Py_DECREF(*exceptionObject);
- *exceptionObject = NULL;
- }
-}
-
-/* raises a UnicodeEncodeError */
-static void raise_encode_exception(PyObject **exceptionObject,
- const char *encoding,
- const Py_UNICODE *unicode, Py_ssize_t size,
- Py_ssize_t startpos, Py_ssize_t endpos,
- const char *reason)
-{
- make_encode_exception(exceptionObject,
- encoding, unicode, size, startpos, endpos, reason);
- if (*exceptionObject != NULL)
- PyCodec_StrictErrors(*exceptionObject);
-}
-
-/* error handling callback helper:
- build arguments, call the callback and check the arguments,
- put the result into newpos and return the replacement string, which
- has to be freed by the caller */
-static PyObject *unicode_encode_call_errorhandler(const char *errors,
- PyObject **errorHandler,
- const char *encoding, const char *reason,
- const Py_UNICODE *unicode, Py_ssize_t size, PyObject **exceptionObject,
- Py_ssize_t startpos, Py_ssize_t endpos,
- Py_ssize_t *newpos)
-{
- static char *argparse = "O!n;encoding error handler must return (unicode, int) tuple";
-
- PyObject *restuple;
- PyObject *resunicode;
-
- if (*errorHandler == NULL) {
- *errorHandler = PyCodec_LookupError(errors);
- if (*errorHandler == NULL)
- return NULL;
- }
-
- make_encode_exception(exceptionObject,
- encoding, unicode, size, startpos, endpos, reason);
- if (*exceptionObject == NULL)
- return NULL;
-
- restuple = PyObject_CallFunctionObjArgs(
- *errorHandler, *exceptionObject, NULL);
- if (restuple == NULL)
- return NULL;
- if (!PyTuple_Check(restuple)) {
- PyErr_Format(PyExc_TypeError, &argparse[4]);
- Py_DECREF(restuple);
- return NULL;
- }
- if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type,
- &resunicode, newpos)) {
- Py_DECREF(restuple);
- return NULL;
- }
- if (*newpos<0)
- *newpos = size+*newpos;
- if (*newpos<0 || *newpos>size) {
- PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", *newpos);
- Py_DECREF(restuple);
- return NULL;
- }
- Py_INCREF(resunicode);
- Py_DECREF(restuple);
- return resunicode;
-}
-
-static PyObject *unicode_encode_ucs1(const Py_UNICODE *p,
- Py_ssize_t size,
- const char *errors,
- int limit)
-{
- /* output object */
- PyObject *res;
- /* pointers to the beginning and end+1 of input */
- const Py_UNICODE *startp = p;
- const Py_UNICODE *endp = p + size;
- /* pointer to the beginning of the unencodable characters */
- /* const Py_UNICODE *badp = NULL; */
- /* pointer into the output */
- char *str;
- /* current output position */
- Py_ssize_t respos = 0;
- Py_ssize_t ressize;
- const char *encoding = (limit == 256) ? "latin-1" : "ascii";
- const char *reason = (limit == 256) ? "ordinal not in range(256)" : "ordinal not in range(128)";
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
- /* the following variable is used for caching string comparisons
- * -1=not initialized, 0=unknown, 1=strict, 2=replace, 3=ignore, 4=xmlcharrefreplace */
- int known_errorHandler = -1;
-
- /* allocate enough for a simple encoding without
- replacements, if we need more, we'll resize */
- res = PyString_FromStringAndSize(NULL, size);
- if (res == NULL)
- goto onError;
- if (size == 0)
- return res;
- str = PyString_AS_STRING(res);
- ressize = size;
-
- while (p<endp) {
- Py_UNICODE c = *p;
-
- /* can we encode this? */
- if (c<limit) {
- /* no overflow check, because we know that the space is enough */
- *str++ = (char)c;
- ++p;
- }
- else {
- Py_ssize_t unicodepos = p-startp;
- Py_ssize_t requiredsize;
- PyObject *repunicode;
- Py_ssize_t repsize;
- Py_ssize_t newpos;
- Py_ssize_t respos;
- Py_UNICODE *uni2;
- /* startpos for collecting unencodable chars */
- const Py_UNICODE *collstart = p;
- const Py_UNICODE *collend = p;
- /* find all unecodable characters */
- while ((collend < endp) && ((*collend)>=limit))
- ++collend;
- /* cache callback name lookup (if not done yet, i.e. it's the first error) */
- if (known_errorHandler==-1) {
- if ((errors==NULL) || (!strcmp(errors, "strict")))
- known_errorHandler = 1;
- else if (!strcmp(errors, "replace"))
- known_errorHandler = 2;
- else if (!strcmp(errors, "ignore"))
- known_errorHandler = 3;
- else if (!strcmp(errors, "xmlcharrefreplace"))
- known_errorHandler = 4;
- else
- known_errorHandler = 0;
- }
- switch (known_errorHandler) {
- case 1: /* strict */
- raise_encode_exception(&exc, encoding, startp, size, collstart-startp, collend-startp, reason);
- goto onError;
- case 2: /* replace */
- while (collstart++<collend)
- *str++ = '?'; /* fall through */
- case 3: /* ignore */
- p = collend;
- break;
- case 4: /* xmlcharrefreplace */
- respos = str-PyString_AS_STRING(res);
- /* determine replacement size (temporarily (mis)uses p) */
- for (p = collstart, repsize = 0; p < collend; ++p) {
- if (*p<10)
- repsize += 2+1+1;
- else if (*p<100)
- repsize += 2+2+1;
- else if (*p<1000)
- repsize += 2+3+1;
- else if (*p<10000)
- repsize += 2+4+1;
-#ifndef Py_UNICODE_WIDE
- else
- repsize += 2+5+1;
-#else
- else if (*p<100000)
- repsize += 2+5+1;
- else if (*p<1000000)
- repsize += 2+6+1;
- else
- repsize += 2+7+1;
-#endif
- }
- requiredsize = respos+repsize+(endp-collend);
- if (requiredsize > ressize) {
- if (requiredsize<2*ressize)
- requiredsize = 2*ressize;
- if (_PyString_Resize(&res, requiredsize))
- goto onError;
- str = PyString_AS_STRING(res) + respos;
- ressize = requiredsize;
- }
- /* generate replacement (temporarily (mis)uses p) */
- for (p = collstart; p < collend; ++p) {
- str += sprintf(str, "&#%d;", (int)*p);
- }
- p = collend;
- break;
- default:
- repunicode = unicode_encode_call_errorhandler(errors, &errorHandler,
- encoding, reason, startp, size, &exc,
- collstart-startp, collend-startp, &newpos);
- if (repunicode == NULL)
- goto onError;
- /* need more space? (at least enough for what we
- have+the replacement+the rest of the string, so
- we won't have to check space for encodable characters) */
- respos = str-PyString_AS_STRING(res);
- repsize = PyUnicode_GET_SIZE(repunicode);
- requiredsize = respos+repsize+(endp-collend);
- if (requiredsize > ressize) {
- if (requiredsize<2*ressize)
- requiredsize = 2*ressize;
- if (_PyString_Resize(&res, requiredsize)) {
- Py_DECREF(repunicode);
- goto onError;
- }
- str = PyString_AS_STRING(res) + respos;
- ressize = requiredsize;
- }
- /* check if there is anything unencodable in the replacement
- and copy it to the output */
- for (uni2 = PyUnicode_AS_UNICODE(repunicode);repsize-->0; ++uni2, ++str) {
- c = *uni2;
- if (c >= limit) {
- raise_encode_exception(&exc, encoding, startp, size,
- unicodepos, unicodepos+1, reason);
- Py_DECREF(repunicode);
- goto onError;
- }
- *str = (char)c;
- }
- p = startp + newpos;
- Py_DECREF(repunicode);
- }
- }
- }
- /* Resize if we allocated to much */
- respos = str-PyString_AS_STRING(res);
- if (respos<ressize)
- /* If this falls res will be NULL */
- _PyString_Resize(&res, respos);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return res;
-
- onError:
- Py_XDECREF(res);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-}
-
-PyObject *PyUnicode_EncodeLatin1(const Py_UNICODE *p,
- Py_ssize_t size,
- const char *errors)
-{
- return unicode_encode_ucs1(p, size, errors, 256);
-}
-
-PyObject *PyUnicode_AsLatin1String(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeLatin1(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode),
- NULL);
-}
-
-/* --- 7-bit ASCII Codec -------------------------------------------------- */
-
-PyObject *PyUnicode_DecodeASCII(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- const char *starts = s;
- PyUnicodeObject *v;
- Py_UNICODE *p;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- const char *e;
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
-
- /* ASCII is equivalent to the first 128 ordinals in Unicode. */
- if (size == 1 && *(unsigned char*)s < 128) {
- Py_UNICODE r = *(unsigned char*)s;
- return PyUnicode_FromUnicode(&r, 1);
- }
-
- v = _PyUnicode_New(size);
- if (v == NULL)
- goto onError;
- if (size == 0)
- return (PyObject *)v;
- p = PyUnicode_AS_UNICODE(v);
- e = s + size;
- while (s < e) {
- register unsigned char c = (unsigned char)*s;
- if (c < 128) {
- *p++ = c;
- ++s;
- }
- else {
- startinpos = s-starts;
- endinpos = startinpos + 1;
- outpos = p - (Py_UNICODE *)PyUnicode_AS_UNICODE(v);
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "ascii", "ordinal not in range(128)",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p))
- goto onError;
- }
- }
- if (p - PyUnicode_AS_UNICODE(v) < PyString_GET_SIZE(v))
- if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)
- goto onError;
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)v;
-
- onError:
- Py_XDECREF(v);
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return NULL;
-}
-
-PyObject *PyUnicode_EncodeASCII(const Py_UNICODE *p,
- Py_ssize_t size,
- const char *errors)
-{
- return unicode_encode_ucs1(p, size, errors, 128);
-}
-
-PyObject *PyUnicode_AsASCIIString(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeASCII(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode),
- NULL);
-}
-
-#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
-
-/* --- MBCS codecs for Windows -------------------------------------------- */
-
-#if SIZEOF_INT < SIZEOF_SSIZE_T
-#define NEED_RETRY
-#endif
-
-/* XXX This code is limited to "true" double-byte encodings, as
- a) it assumes an incomplete character consists of a single byte, and
- b) IsDBCSLeadByte (probably) does not work for non-DBCS multi-byte
- encodings, see IsDBCSLeadByteEx documentation. */
-
-static int is_dbcs_lead_byte(const char *s, int offset)
-{
- const char *curr = s + offset;
-
- if (IsDBCSLeadByte(*curr)) {
- const char *prev = CharPrev(s, curr);
- return (prev == curr) || !IsDBCSLeadByte(*prev) || (curr - prev == 2);
- }
- return 0;
-}
-
-/*
- * Decode MBCS string into unicode object. If 'final' is set, converts
- * trailing lead-byte too. Returns consumed size if succeed, -1 otherwise.
- */
-static int decode_mbcs(PyUnicodeObject **v,
- const char *s, /* MBCS string */
- int size, /* sizeof MBCS string */
- int final)
-{
- Py_UNICODE *p;
- Py_ssize_t n = 0;
- int usize = 0;
-
- assert(size >= 0);
-
- /* Skip trailing lead-byte unless 'final' is set */
- if (!final && size >= 1 && is_dbcs_lead_byte(s, size - 1))
- --size;
-
- /* First get the size of the result */
- if (size > 0) {
- usize = MultiByteToWideChar(CP_ACP, 0, s, size, NULL, 0);
- if (usize == 0) {
- PyErr_SetFromWindowsErrWithFilename(0, NULL);
- return -1;
- }
- }
-
- if (*v == NULL) {
- /* Create unicode object */
- *v = _PyUnicode_New(usize);
- if (*v == NULL)
- return -1;
- }
- else {
- /* Extend unicode object */
- n = PyUnicode_GET_SIZE(*v);
- if (_PyUnicode_Resize(v, n + usize) < 0)
- return -1;
- }
-
- /* Do the conversion */
- if (size > 0) {
- p = PyUnicode_AS_UNICODE(*v) + n;
- if (0 == MultiByteToWideChar(CP_ACP, 0, s, size, p, usize)) {
- PyErr_SetFromWindowsErrWithFilename(0, NULL);
- return -1;
- }
- }
-
- return size;
-}
-
-PyObject *PyUnicode_DecodeMBCSStateful(const char *s,
- Py_ssize_t size,
- const char *errors,
- Py_ssize_t *consumed)
-{
- PyUnicodeObject *v = NULL;
- int done;
-
- if (consumed)
- *consumed = 0;
-
-#ifdef NEED_RETRY
- retry:
- if (size > INT_MAX)
- done = decode_mbcs(&v, s, INT_MAX, 0);
- else
-#endif
- done = decode_mbcs(&v, s, (int)size, !consumed);
-
- if (done < 0) {
- Py_XDECREF(v);
- return NULL;
- }
-
- if (consumed)
- *consumed += done;
-
-#ifdef NEED_RETRY
- if (size > INT_MAX) {
- s += done;
- size -= done;
- goto retry;
- }
-#endif
-
- return (PyObject *)v;
-}
-
-PyObject *PyUnicode_DecodeMBCS(const char *s,
- Py_ssize_t size,
- const char *errors)
-{
- return PyUnicode_DecodeMBCSStateful(s, size, errors, NULL);
-}
-
-/*
- * Convert unicode into string object (MBCS).
- * Returns 0 if succeed, -1 otherwise.
- */
-static int encode_mbcs(PyObject **repr,
- const Py_UNICODE *p, /* unicode */
- int size) /* size of unicode */
-{
- int mbcssize = 0;
- Py_ssize_t n = 0;
-
- assert(size >= 0);
-
- /* First get the size of the result */
- if (size > 0) {
- mbcssize = WideCharToMultiByte(CP_ACP, 0, p, size, NULL, 0, NULL, NULL);
- if (mbcssize == 0) {
- PyErr_SetFromWindowsErrWithFilename(0, NULL);
- return -1;
- }
- }
-
- if (*repr == NULL) {
- /* Create string object */
- *repr = PyString_FromStringAndSize(NULL, mbcssize);
- if (*repr == NULL)
- return -1;
- }
- else {
- /* Extend string object */
- n = PyString_Size(*repr);
- if (_PyString_Resize(repr, n + mbcssize) < 0)
- return -1;
- }
-
- /* Do the conversion */
- if (size > 0) {
- char *s = PyString_AS_STRING(*repr) + n;
- if (0 == WideCharToMultiByte(CP_ACP, 0, p, size, s, mbcssize, NULL, NULL)) {
- PyErr_SetFromWindowsErrWithFilename(0, NULL);
- return -1;
- }
- }
-
- return 0;
-}
-
-PyObject *PyUnicode_EncodeMBCS(const Py_UNICODE *p,
- Py_ssize_t size,
- const char *errors)
-{
- PyObject *repr = NULL;
- int ret;
-
-#ifdef NEED_RETRY
- retry:
- if (size > INT_MAX)
- ret = encode_mbcs(&repr, p, INT_MAX);
- else
-#endif
- ret = encode_mbcs(&repr, p, (int)size);
-
- if (ret < 0) {
- Py_XDECREF(repr);
- return NULL;
- }
-
-#ifdef NEED_RETRY
- if (size > INT_MAX) {
- p += INT_MAX;
- size -= INT_MAX;
- goto retry;
- }
-#endif
-
- return repr;
-}
-
-PyObject *PyUnicode_AsMBCSString(PyObject *unicode)
-{
- if (!PyUnicode_Check(unicode)) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeMBCS(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode),
- NULL);
-}
-
-#undef NEED_RETRY
-
-#endif /* MS_WINDOWS */
-
-/* --- Character Mapping Codec -------------------------------------------- */
-
-PyObject *PyUnicode_DecodeCharmap(const char *s,
- Py_ssize_t size,
- PyObject *mapping,
- const char *errors)
-{
- const char *starts = s;
- Py_ssize_t startinpos;
- Py_ssize_t endinpos;
- Py_ssize_t outpos;
- const char *e;
- PyUnicodeObject *v;
- Py_UNICODE *p;
- Py_ssize_t extrachars = 0;
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
- Py_UNICODE *mapstring = NULL;
- Py_ssize_t maplen = 0;
-
- /* Default to Latin-1 */
- if (mapping == NULL)
- return PyUnicode_DecodeLatin1(s, size, errors);
-
- v = _PyUnicode_New(size);
- if (v == NULL)
- goto onError;
- if (size == 0)
- return (PyObject *)v;
- p = PyUnicode_AS_UNICODE(v);
- e = s + size;
- if (PyUnicode_CheckExact(mapping)) {
- mapstring = PyUnicode_AS_UNICODE(mapping);
- maplen = PyUnicode_GET_SIZE(mapping);
- while (s < e) {
- unsigned char ch = *s;
- Py_UNICODE x = 0xfffe; /* illegal value */
-
- if (ch < maplen)
- x = mapstring[ch];
-
- if (x == 0xfffe) {
- /* undefined mapping */
- outpos = p-PyUnicode_AS_UNICODE(v);
- startinpos = s-starts;
- endinpos = startinpos+1;
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "charmap", "character maps to <undefined>",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p)) {
- goto onError;
- }
- continue;
- }
- *p++ = x;
- ++s;
- }
- }
- else {
- while (s < e) {
- unsigned char ch = *s;
- PyObject *w, *x;
-
- /* Get mapping (char ordinal -> integer, Unicode char or None) */
- w = PyInt_FromLong((long)ch);
- if (w == NULL)
- goto onError;
- x = PyObject_GetItem(mapping, w);
- Py_DECREF(w);
- if (x == NULL) {
- if (PyErr_ExceptionMatches(PyExc_LookupError)) {
- /* No mapping found means: mapping is undefined. */
- PyErr_Clear();
- x = Py_None;
- Py_INCREF(x);
- } else
- goto onError;
- }
-
- /* Apply mapping */
- if (PyInt_Check(x)) {
- long value = PyInt_AS_LONG(x);
- if (value < 0 || value > 65535) {
- PyErr_SetString(PyExc_TypeError,
- "character mapping must be in range(65536)");
- Py_DECREF(x);
- goto onError;
- }
- *p++ = (Py_UNICODE)value;
- }
- else if (x == Py_None) {
- /* undefined mapping */
- outpos = p-PyUnicode_AS_UNICODE(v);
- startinpos = s-starts;
- endinpos = startinpos+1;
- if (unicode_decode_call_errorhandler(
- errors, &errorHandler,
- "charmap", "character maps to <undefined>",
- starts, size, &startinpos, &endinpos, &exc, &s,
- (PyObject **)&v, &outpos, &p)) {
- Py_DECREF(x);
- goto onError;
- }
- Py_DECREF(x);
- continue;
- }
- else if (PyUnicode_Check(x)) {
- Py_ssize_t targetsize = PyUnicode_GET_SIZE(x);
-
- if (targetsize == 1)
- /* 1-1 mapping */
- *p++ = *PyUnicode_AS_UNICODE(x);
-
- else if (targetsize > 1) {
- /* 1-n mapping */
- if (targetsize > extrachars) {
- /* resize first */
- Py_ssize_t oldpos = p - PyUnicode_AS_UNICODE(v);
- Py_ssize_t needed = (targetsize - extrachars) + \
- (targetsize << 2);
- extrachars += needed;
- /* XXX overflow detection missing */
- if (_PyUnicode_Resize(&v,
- PyUnicode_GET_SIZE(v) + needed) < 0) {
- Py_DECREF(x);
- goto onError;
- }
- p = PyUnicode_AS_UNICODE(v) + oldpos;
- }
- Py_UNICODE_COPY(p,
- PyUnicode_AS_UNICODE(x),
- targetsize);
- p += targetsize;
- extrachars -= targetsize;
- }
- /* 1-0 mapping: skip the character */
- }
- else {
- /* wrong return value */
- PyErr_SetString(PyExc_TypeError,
- "character mapping must return integer, None or unicode");
- Py_DECREF(x);
- goto onError;
- }
- Py_DECREF(x);
- ++s;
- }
- }
- if (p - PyUnicode_AS_UNICODE(v) < PyUnicode_GET_SIZE(v))
- if (_PyUnicode_Resize(&v, p - PyUnicode_AS_UNICODE(v)) < 0)
- goto onError;
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- return (PyObject *)v;
-
- onError:
- Py_XDECREF(errorHandler);
- Py_XDECREF(exc);
- Py_XDECREF(v);
- return NULL;
-}
-
-/* Charmap encoding: the lookup table */
-
-struct encoding_map{
- PyObject_HEAD
- unsigned char level1[32];
- int count2, count3;
- unsigned char level23[1];
-};
-
-static PyObject*
-encoding_map_size(PyObject *obj, PyObject* args)
-{
- struct encoding_map *map = (struct encoding_map*)obj;
- return PyInt_FromLong(sizeof(*map) - 1 + 16*map->count2 +
- 128*map->count3);
-}
-
-static PyMethodDef encoding_map_methods[] = {
- {"size", encoding_map_size, METH_NOARGS,
- PyDoc_STR("Return the size (in bytes) of this object") },
- { 0 }
-};
-
-static void
-encoding_map_dealloc(PyObject* o)
-{
- PyObject_FREE(o);
-}
-
-static PyTypeObject EncodingMapType = {
- PyObject_HEAD_INIT(NULL)
- 0, /*ob_size*/
- "EncodingMap", /*tp_name*/
- sizeof(struct encoding_map), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- encoding_map_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- 0, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT, /*tp_flags*/
- 0, /*tp_doc*/
- 0, /*tp_traverse*/
- 0, /*tp_clear*/
- 0, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- encoding_map_methods, /*tp_methods*/
- 0, /*tp_members*/
- 0, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- 0, /*tp_init*/
- 0, /*tp_alloc*/
- 0, /*tp_new*/
- 0, /*tp_free*/
- 0, /*tp_is_gc*/
-};
-
-PyObject*
-PyUnicode_BuildEncodingMap(PyObject* string)
-{
- Py_UNICODE *decode;
- PyObject *result;
- struct encoding_map *mresult;
- int i;
- int need_dict = 0;
- unsigned char level1[32];
- unsigned char level2[512];
- unsigned char *mlevel1, *mlevel2, *mlevel3;
- int count2 = 0, count3 = 0;
-
- if (!PyUnicode_Check(string) || PyUnicode_GetSize(string) != 256) {
- PyErr_BadArgument();
- return NULL;
- }
- decode = PyUnicode_AS_UNICODE(string);
- memset(level1, 0xFF, sizeof level1);
- memset(level2, 0xFF, sizeof level2);
-
- /* If there isn't a one-to-one mapping of NULL to \0,
- or if there are non-BMP characters, we need to use
- a mapping dictionary. */
- if (decode[0] != 0)
- need_dict = 1;
- for (i = 1; i < 256; i++) {
- int l1, l2;
- if (decode[i] == 0
- #ifdef Py_UNICODE_WIDE
- || decode[i] > 0xFFFF
- #endif
- ) {
- need_dict = 1;
- break;
- }
- if (decode[i] == 0xFFFE)
- /* unmapped character */
- continue;
- l1 = decode[i] >> 11;
- l2 = decode[i] >> 7;
- if (level1[l1] == 0xFF)
- level1[l1] = count2++;
- if (level2[l2] == 0xFF)
- level2[l2] = count3++;
- }
-
- if (count2 >= 0xFF || count3 >= 0xFF)
- need_dict = 1;
-
- if (need_dict) {
- PyObject *result = PyDict_New();
- PyObject *key, *value;
- if (!result)
- return NULL;
- for (i = 0; i < 256; i++) {
- key = value = NULL;
- key = PyInt_FromLong(decode[i]);
- value = PyInt_FromLong(i);
- if (!key || !value)
- goto failed1;
- if (PyDict_SetItem(result, key, value) == -1)
- goto failed1;
- Py_DECREF(key);
- Py_DECREF(value);
- }
- return result;
- failed1:
- Py_XDECREF(key);
- Py_XDECREF(value);
- Py_DECREF(result);
- return NULL;
- }
-
- /* Create a three-level trie */
- result = PyObject_MALLOC(sizeof(struct encoding_map) +
- 16*count2 + 128*count3 - 1);
- if (!result)
- return PyErr_NoMemory();
- PyObject_Init(result, &EncodingMapType);
- mresult = (struct encoding_map*)result;
- mresult->count2 = count2;
- mresult->count3 = count3;
- mlevel1 = mresult->level1;
- mlevel2 = mresult->level23;
- mlevel3 = mresult->level23 + 16*count2;
- memcpy(mlevel1, level1, 32);
- memset(mlevel2, 0xFF, 16*count2);
- memset(mlevel3, 0, 128*count3);
- count3 = 0;
- for (i = 1; i < 256; i++) {
- int o1, o2, o3, i2, i3;
- if (decode[i] == 0xFFFE)
- /* unmapped character */
- continue;
- o1 = decode[i]>>11;
- o2 = (decode[i]>>7) & 0xF;
- i2 = 16*mlevel1[o1] + o2;
- if (mlevel2[i2] == 0xFF)
- mlevel2[i2] = count3++;
- o3 = decode[i] & 0x7F;
- i3 = 128*mlevel2[i2] + o3;
- mlevel3[i3] = i;
- }
- return result;
-}
-
-static int
-encoding_map_lookup(Py_UNICODE c, PyObject *mapping)
-{
- struct encoding_map *map = (struct encoding_map*)mapping;
- int l1 = c>>11;
- int l2 = (c>>7) & 0xF;
- int l3 = c & 0x7F;
- int i;
-
-#ifdef Py_UNICODE_WIDE
- if (c > 0xFFFF) {
- return -1;
- }
-#endif
- if (c == 0)
- return 0;
- /* level 1*/
- i = map->level1[l1];
- if (i == 0xFF) {
- return -1;
- }
- /* level 2*/
- i = map->level23[16*i+l2];
- if (i == 0xFF) {
- return -1;
- }
- /* level 3 */
- i = map->level23[16*map->count2 + 128*i + l3];
- if (i == 0) {
- return -1;
- }
- return i;
-}
-
-/* Lookup the character ch in the mapping. If the character
- can't be found, Py_None is returned (or NULL, if another
- error occurred). */
-static PyObject *charmapencode_lookup(Py_UNICODE c, PyObject *mapping)
-{
- PyObject *w = PyInt_FromLong((long)c);
- PyObject *x;
-
- if (w == NULL)
- return NULL;
- x = PyObject_GetItem(mapping, w);
- Py_DECREF(w);
- if (x == NULL) {
- if (PyErr_ExceptionMatches(PyExc_LookupError)) {
- /* No mapping found means: mapping is undefined. */
- PyErr_Clear();
- x = Py_None;
- Py_INCREF(x);
- return x;
- } else
- return NULL;
- }
- else if (x == Py_None)
- return x;
- else if (PyInt_Check(x)) {
- long value = PyInt_AS_LONG(x);
- if (value < 0 || value > 255) {
- PyErr_SetString(PyExc_TypeError,
- "character mapping must be in range(256)");
- Py_DECREF(x);
- return NULL;
- }
- return x;
- }
- else if (PyString_Check(x))
- return x;
- else {
- /* wrong return value */
- PyErr_SetString(PyExc_TypeError,
- "character mapping must return integer, None or str");
- Py_DECREF(x);
- return NULL;
- }
-}
-
-static int
-charmapencode_resize(PyObject **outobj, Py_ssize_t *outpos, Py_ssize_t requiredsize)
-{
- Py_ssize_t outsize = PyString_GET_SIZE(*outobj);
- /* exponentially overallocate to minimize reallocations */
- if (requiredsize < 2*outsize)
- requiredsize = 2*outsize;
- if (_PyString_Resize(outobj, requiredsize)) {
- return 0;
- }
- return 1;
-}
-
-typedef enum charmapencode_result {
- enc_SUCCESS, enc_FAILED, enc_EXCEPTION
-}charmapencode_result;
-/* lookup the character, put the result in the output string and adjust
- various state variables. Reallocate the output string if not enough
- space is available. Return a new reference to the object that
- was put in the output buffer, or Py_None, if the mapping was undefined
- (in which case no character was written) or NULL, if a
- reallocation error occurred. The caller must decref the result */
-static
-charmapencode_result charmapencode_output(Py_UNICODE c, PyObject *mapping,
- PyObject **outobj, Py_ssize_t *outpos)
-{
- PyObject *rep;
- char *outstart;
- Py_ssize_t outsize = PyString_GET_SIZE(*outobj);
-
- if (mapping->ob_type == &EncodingMapType) {
- int res = encoding_map_lookup(c, mapping);
- Py_ssize_t requiredsize = *outpos+1;
- if (res == -1)
- return enc_FAILED;
- if (outsize<requiredsize)
- if (!charmapencode_resize(outobj, outpos, requiredsize))
- return enc_EXCEPTION;
- outstart = PyString_AS_STRING(*outobj);
- outstart[(*outpos)++] = (char)res;
- return enc_SUCCESS;
- }
-
- rep = charmapencode_lookup(c, mapping);
- if (rep==NULL)
- return enc_EXCEPTION;
- else if (rep==Py_None) {
- Py_DECREF(rep);
- return enc_FAILED;
- } else {
- if (PyInt_Check(rep)) {
- Py_ssize_t requiredsize = *outpos+1;
- if (outsize<requiredsize)
- if (!charmapencode_resize(outobj, outpos, requiredsize)) {
- Py_DECREF(rep);
- return enc_EXCEPTION;
- }
- outstart = PyString_AS_STRING(*outobj);
- outstart[(*outpos)++] = (char)PyInt_AS_LONG(rep);
- }
- else {
- const char *repchars = PyString_AS_STRING(rep);
- Py_ssize_t repsize = PyString_GET_SIZE(rep);
- Py_ssize_t requiredsize = *outpos+repsize;
- if (outsize<requiredsize)
- if (!charmapencode_resize(outobj, outpos, requiredsize)) {
- Py_DECREF(rep);
- return enc_EXCEPTION;
- }
- outstart = PyString_AS_STRING(*outobj);
- memcpy(outstart + *outpos, repchars, repsize);
- *outpos += repsize;
- }
- }
- Py_DECREF(rep);
- return enc_SUCCESS;
-}
-
-/* handle an error in PyUnicode_EncodeCharmap
- Return 0 on success, -1 on error */
-static
-int charmap_encoding_error(
- const Py_UNICODE *p, Py_ssize_t size, Py_ssize_t *inpos, PyObject *mapping,
- PyObject **exceptionObject,
- int *known_errorHandler, PyObject **errorHandler, const char *errors,
- PyObject **res, Py_ssize_t *respos)
-{
- PyObject *repunicode = NULL; /* initialize to prevent gcc warning */
- Py_ssize_t repsize;
- Py_ssize_t newpos;
- Py_UNICODE *uni2;
- /* startpos for collecting unencodable chars */
- Py_ssize_t collstartpos = *inpos;
- Py_ssize_t collendpos = *inpos+1;
- Py_ssize_t collpos;
- char *encoding = "charmap";
- char *reason = "character maps to <undefined>";
- charmapencode_result x;
-
- /* find all unencodable characters */
- while (collendpos < size) {
- PyObject *rep;
- if (mapping->ob_type == &EncodingMapType) {
- int res = encoding_map_lookup(p[collendpos], mapping);
- if (res != -1)
- break;
- ++collendpos;
- continue;
- }
-
- rep = charmapencode_lookup(p[collendpos], mapping);
- if (rep==NULL)
- return -1;
- else if (rep!=Py_None) {
- Py_DECREF(rep);
- break;
- }
- Py_DECREF(rep);
- ++collendpos;
- }
- /* cache callback name lookup
- * (if not done yet, i.e. it's the first error) */
- if (*known_errorHandler==-1) {
- if ((errors==NULL) || (!strcmp(errors, "strict")))
- *known_errorHandler = 1;
- else if (!strcmp(errors, "replace"))
- *known_errorHandler = 2;
- else if (!strcmp(errors, "ignore"))
- *known_errorHandler = 3;
- else if (!strcmp(errors, "xmlcharrefreplace"))
- *known_errorHandler = 4;
- else
- *known_errorHandler = 0;
- }
- switch (*known_errorHandler) {
- case 1: /* strict */
- raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);
- return -1;
- case 2: /* replace */
- for (collpos = collstartpos; collpos<collendpos; ++collpos) {
- x = charmapencode_output('?', mapping, res, respos);
- if (x==enc_EXCEPTION) {
- return -1;
- }
- else if (x==enc_FAILED) {
- raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);
- return -1;
- }
- }
- /* fall through */
- case 3: /* ignore */
- *inpos = collendpos;
- break;
- case 4: /* xmlcharrefreplace */
- /* generate replacement (temporarily (mis)uses p) */
- for (collpos = collstartpos; collpos < collendpos; ++collpos) {
- char buffer[2+29+1+1];
- char *cp;
- sprintf(buffer, "&#%d;", (int)p[collpos]);
- for (cp = buffer; *cp; ++cp) {
- x = charmapencode_output(*cp, mapping, res, respos);
- if (x==enc_EXCEPTION)
- return -1;
- else if (x==enc_FAILED) {
- raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);
- return -1;
- }
- }
- }
- *inpos = collendpos;
- break;
- default:
- repunicode = unicode_encode_call_errorhandler(errors, errorHandler,
- encoding, reason, p, size, exceptionObject,
- collstartpos, collendpos, &newpos);
- if (repunicode == NULL)
- return -1;
- /* generate replacement */
- repsize = PyUnicode_GET_SIZE(repunicode);
- for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2) {
- x = charmapencode_output(*uni2, mapping, res, respos);
- if (x==enc_EXCEPTION) {
- return -1;
- }
- else if (x==enc_FAILED) {
- Py_DECREF(repunicode);
- raise_encode_exception(exceptionObject, encoding, p, size, collstartpos, collendpos, reason);
- return -1;
- }
- }
- *inpos = newpos;
- Py_DECREF(repunicode);
- }
- return 0;
-}
-
-PyObject *PyUnicode_EncodeCharmap(const Py_UNICODE *p,
- Py_ssize_t size,
- PyObject *mapping,
- const char *errors)
-{
- /* output object */
- PyObject *res = NULL;
- /* current input position */
- Py_ssize_t inpos = 0;
- /* current output position */
- Py_ssize_t respos = 0;
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
- /* the following variable is used for caching string comparisons
- * -1=not initialized, 0=unknown, 1=strict, 2=replace,
- * 3=ignore, 4=xmlcharrefreplace */
- int known_errorHandler = -1;
-
- /* Default to Latin-1 */
- if (mapping == NULL)
- return PyUnicode_EncodeLatin1(p, size, errors);
-
- /* allocate enough for a simple encoding without
- replacements, if we need more, we'll resize */
- res = PyString_FromStringAndSize(NULL, size);
- if (res == NULL)
- goto onError;
- if (size == 0)
- return res;
-
- while (inpos<size) {
- /* try to encode it */
- charmapencode_result x = charmapencode_output(p[inpos], mapping, &res, &respos);
- if (x==enc_EXCEPTION) /* error */
- goto onError;
- if (x==enc_FAILED) { /* unencodable character */
- if (charmap_encoding_error(p, size, &inpos, mapping,
- &exc,
- &known_errorHandler, &errorHandler, errors,
- &res, &respos)) {
- goto onError;
- }
- }
- else
- /* done with this character => adjust input position */
- ++inpos;
- }
-
- /* Resize if we allocated to much */
- if (respos<PyString_GET_SIZE(res)) {
- if (_PyString_Resize(&res, respos))
- goto onError;
- }
- Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
- return res;
-
- onError:
- Py_XDECREF(res);
- Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
- return NULL;
-}
-
-PyObject *PyUnicode_AsCharmapString(PyObject *unicode,
- PyObject *mapping)
-{
- if (!PyUnicode_Check(unicode) || mapping == NULL) {
- PyErr_BadArgument();
- return NULL;
- }
- return PyUnicode_EncodeCharmap(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode),
- mapping,
- NULL);
-}
-
-/* create or adjust a UnicodeTranslateError */
-static void make_translate_exception(PyObject **exceptionObject,
- const Py_UNICODE *unicode, Py_ssize_t size,
- Py_ssize_t startpos, Py_ssize_t endpos,
- const char *reason)
-{
- if (*exceptionObject == NULL) {
- *exceptionObject = PyUnicodeTranslateError_Create(
- unicode, size, startpos, endpos, reason);
- }
- else {
- if (PyUnicodeTranslateError_SetStart(*exceptionObject, startpos))
- goto onError;
- if (PyUnicodeTranslateError_SetEnd(*exceptionObject, endpos))
- goto onError;
- if (PyUnicodeTranslateError_SetReason(*exceptionObject, reason))
- goto onError;
- return;
- onError:
- Py_DECREF(*exceptionObject);
- *exceptionObject = NULL;
- }
-}
-
-/* raises a UnicodeTranslateError */
-static void raise_translate_exception(PyObject **exceptionObject,
- const Py_UNICODE *unicode, Py_ssize_t size,
- Py_ssize_t startpos, Py_ssize_t endpos,
- const char *reason)
-{
- make_translate_exception(exceptionObject,
- unicode, size, startpos, endpos, reason);
- if (*exceptionObject != NULL)
- PyCodec_StrictErrors(*exceptionObject);
-}
-
-/* error handling callback helper:
- build arguments, call the callback and check the arguments,
- put the result into newpos and return the replacement string, which
- has to be freed by the caller */
-static PyObject *unicode_translate_call_errorhandler(const char *errors,
- PyObject **errorHandler,
- const char *reason,
- const Py_UNICODE *unicode, Py_ssize_t size, PyObject **exceptionObject,
- Py_ssize_t startpos, Py_ssize_t endpos,
- Py_ssize_t *newpos)
-{
- static char *argparse = "O!n;translating error handler must return (unicode, int) tuple";
-
- Py_ssize_t i_newpos;
- PyObject *restuple;
- PyObject *resunicode;
-
- if (*errorHandler == NULL) {
- *errorHandler = PyCodec_LookupError(errors);
- if (*errorHandler == NULL)
- return NULL;
- }
-
- make_translate_exception(exceptionObject,
- unicode, size, startpos, endpos, reason);
- if (*exceptionObject == NULL)
- return NULL;
-
- restuple = PyObject_CallFunctionObjArgs(
- *errorHandler, *exceptionObject, NULL);
- if (restuple == NULL)
- return NULL;
- if (!PyTuple_Check(restuple)) {
- PyErr_Format(PyExc_TypeError, &argparse[4]);
- Py_DECREF(restuple);
- return NULL;
- }
- if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type,
- &resunicode, &i_newpos)) {
- Py_DECREF(restuple);
- return NULL;
- }
- if (i_newpos<0)
- *newpos = size+i_newpos;
- else
- *newpos = i_newpos;
- if (*newpos<0 || *newpos>size) {
- PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", *newpos);
- Py_DECREF(restuple);
- return NULL;
- }
- Py_INCREF(resunicode);
- Py_DECREF(restuple);
- return resunicode;
-}
-
-/* Lookup the character ch in the mapping and put the result in result,
- which must be decrefed by the caller.
- Return 0 on success, -1 on error */
-static
-int charmaptranslate_lookup(Py_UNICODE c, PyObject *mapping, PyObject **result)
-{
- PyObject *w = PyInt_FromLong((long)c);
- PyObject *x;
-
- if (w == NULL)
- return -1;
- x = PyObject_GetItem(mapping, w);
- Py_DECREF(w);
- if (x == NULL) {
- if (PyErr_ExceptionMatches(PyExc_LookupError)) {
- /* No mapping found means: use 1:1 mapping. */
- PyErr_Clear();
- *result = NULL;
- return 0;
- } else
- return -1;
- }
- else if (x == Py_None) {
- *result = x;
- return 0;
- }
- else if (PyInt_Check(x)) {
- long value = PyInt_AS_LONG(x);
- long max = PyUnicode_GetMax();
- if (value < 0 || value > max) {
- PyErr_Format(PyExc_TypeError,
- "character mapping must be in range(0x%lx)", max+1);
- Py_DECREF(x);
- return -1;
- }
- *result = x;
- return 0;
- }
- else if (PyUnicode_Check(x)) {
- *result = x;
- return 0;
- }
- else {
- /* wrong return value */
- PyErr_SetString(PyExc_TypeError,
- "character mapping must return integer, None or unicode");
- Py_DECREF(x);
- return -1;
- }
-}
-/* ensure that *outobj is at least requiredsize characters long,
-if not reallocate and adjust various state variables.
-Return 0 on success, -1 on error */
-static
-int charmaptranslate_makespace(PyObject **outobj, Py_UNICODE **outp,
- Py_ssize_t requiredsize)
-{
- Py_ssize_t oldsize = PyUnicode_GET_SIZE(*outobj);
- if (requiredsize > oldsize) {
- /* remember old output position */
- Py_ssize_t outpos = *outp-PyUnicode_AS_UNICODE(*outobj);
- /* exponentially overallocate to minimize reallocations */
- if (requiredsize < 2 * oldsize)
- requiredsize = 2 * oldsize;
- if (_PyUnicode_Resize(outobj, requiredsize) < 0)
- return -1;
- *outp = PyUnicode_AS_UNICODE(*outobj) + outpos;
- }
- return 0;
-}
-/* lookup the character, put the result in the output string and adjust
- various state variables. Return a new reference to the object that
- was put in the output buffer in *result, or Py_None, if the mapping was
- undefined (in which case no character was written).
- The called must decref result.
- Return 0 on success, -1 on error. */
-static
-int charmaptranslate_output(const Py_UNICODE *startinp, const Py_UNICODE *curinp,
- Py_ssize_t insize, PyObject *mapping, PyObject **outobj, Py_UNICODE **outp,
- PyObject **res)
-{
- if (charmaptranslate_lookup(*curinp, mapping, res))
- return -1;
- if (*res==NULL) {
- /* not found => default to 1:1 mapping */
- *(*outp)++ = *curinp;
- }
- else if (*res==Py_None)
- ;
- else if (PyInt_Check(*res)) {
- /* no overflow check, because we know that the space is enough */
- *(*outp)++ = (Py_UNICODE)PyInt_AS_LONG(*res);
- }
- else if (PyUnicode_Check(*res)) {
- Py_ssize_t repsize = PyUnicode_GET_SIZE(*res);
- if (repsize==1) {
- /* no overflow check, because we know that the space is enough */
- *(*outp)++ = *PyUnicode_AS_UNICODE(*res);
- }
- else if (repsize!=0) {
- /* more than one character */
- Py_ssize_t requiredsize = (*outp-PyUnicode_AS_UNICODE(*outobj)) +
- (insize - (curinp-startinp)) +
- repsize - 1;
- if (charmaptranslate_makespace(outobj, outp, requiredsize))
- return -1;
- memcpy(*outp, PyUnicode_AS_UNICODE(*res), sizeof(Py_UNICODE)*repsize);
- *outp += repsize;
- }
- }
- else
- return -1;
- return 0;
-}
-
-PyObject *PyUnicode_TranslateCharmap(const Py_UNICODE *p,
- Py_ssize_t size,
- PyObject *mapping,
- const char *errors)
-{
- /* output object */
- PyObject *res = NULL;
- /* pointers to the beginning and end+1 of input */
- const Py_UNICODE *startp = p;
- const Py_UNICODE *endp = p + size;
- /* pointer into the output */
- Py_UNICODE *str;
- /* current output position */
- Py_ssize_t respos = 0;
- char *reason = "character maps to <undefined>";
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
- /* the following variable is used for caching string comparisons
- * -1=not initialized, 0=unknown, 1=strict, 2=replace,
- * 3=ignore, 4=xmlcharrefreplace */
- int known_errorHandler = -1;
-
- if (mapping == NULL) {
- PyErr_BadArgument();
- return NULL;
- }
-
- /* allocate enough for a simple 1:1 translation without
- replacements, if we need more, we'll resize */
- res = PyUnicode_FromUnicode(NULL, size);
- if (res == NULL)
- goto onError;
- if (size == 0)
- return res;
- str = PyUnicode_AS_UNICODE(res);
-
- while (p<endp) {
- /* try to encode it */
- PyObject *x = NULL;
- if (charmaptranslate_output(startp, p, size, mapping, &res, &str, &x)) {
- Py_XDECREF(x);
- goto onError;
- }
- Py_XDECREF(x);
- if (x!=Py_None) /* it worked => adjust input pointer */
- ++p;
- else { /* untranslatable character */
- PyObject *repunicode = NULL; /* initialize to prevent gcc warning */
- Py_ssize_t repsize;
- Py_ssize_t newpos;
- Py_UNICODE *uni2;
- /* startpos for collecting untranslatable chars */
- const Py_UNICODE *collstart = p;
- const Py_UNICODE *collend = p+1;
- const Py_UNICODE *coll;
-
- /* find all untranslatable characters */
- while (collend < endp) {
- if (charmaptranslate_lookup(*collend, mapping, &x))
- goto onError;
- Py_XDECREF(x);
- if (x!=Py_None)
- break;
- ++collend;
- }
- /* cache callback name lookup
- * (if not done yet, i.e. it's the first error) */
- if (known_errorHandler==-1) {
- if ((errors==NULL) || (!strcmp(errors, "strict")))
- known_errorHandler = 1;
- else if (!strcmp(errors, "replace"))
- known_errorHandler = 2;
- else if (!strcmp(errors, "ignore"))
- known_errorHandler = 3;
- else if (!strcmp(errors, "xmlcharrefreplace"))
- known_errorHandler = 4;
- else
- known_errorHandler = 0;
- }
- switch (known_errorHandler) {
- case 1: /* strict */
- raise_translate_exception(&exc, startp, size, collstart-startp, collend-startp, reason);
- goto onError;
- case 2: /* replace */
- /* No need to check for space, this is a 1:1 replacement */
- for (coll = collstart; coll<collend; ++coll)
- *str++ = '?';
- /* fall through */
- case 3: /* ignore */
- p = collend;
- break;
- case 4: /* xmlcharrefreplace */
- /* generate replacement (temporarily (mis)uses p) */
- for (p = collstart; p < collend; ++p) {
- char buffer[2+29+1+1];
- char *cp;
- sprintf(buffer, "&#%d;", (int)*p);
- if (charmaptranslate_makespace(&res, &str,
- (str-PyUnicode_AS_UNICODE(res))+strlen(buffer)+(endp-collend)))
- goto onError;
- for (cp = buffer; *cp; ++cp)
- *str++ = *cp;
- }
- p = collend;
- break;
- default:
- repunicode = unicode_translate_call_errorhandler(errors, &errorHandler,
- reason, startp, size, &exc,
- collstart-startp, collend-startp, &newpos);
- if (repunicode == NULL)
- goto onError;
- /* generate replacement */
- repsize = PyUnicode_GET_SIZE(repunicode);
- if (charmaptranslate_makespace(&res, &str,
- (str-PyUnicode_AS_UNICODE(res))+repsize+(endp-collend))) {
- Py_DECREF(repunicode);
- goto onError;
- }
- for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2)
- *str++ = *uni2;
- p = startp + newpos;
- Py_DECREF(repunicode);
- }
- }
- }
- /* Resize if we allocated to much */
- respos = str-PyUnicode_AS_UNICODE(res);
- if (respos<PyUnicode_GET_SIZE(res)) {
- if (_PyUnicode_Resize(&res, respos) < 0)
- goto onError;
- }
- Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
- return res;
-
- onError:
- Py_XDECREF(res);
- Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
- return NULL;
-}
-
-PyObject *PyUnicode_Translate(PyObject *str,
- PyObject *mapping,
- const char *errors)
-{
- PyObject *result;
-
- str = PyUnicode_FromObject(str);
- if (str == NULL)
- goto onError;
- result = PyUnicode_TranslateCharmap(PyUnicode_AS_UNICODE(str),
- PyUnicode_GET_SIZE(str),
- mapping,
- errors);
- Py_DECREF(str);
- return result;
-
- onError:
- Py_XDECREF(str);
- return NULL;
-}
-
-/* --- Decimal Encoder ---------------------------------------------------- */
-
-int PyUnicode_EncodeDecimal(Py_UNICODE *s,
- Py_ssize_t length,
- char *output,
- const char *errors)
-{
- Py_UNICODE *p, *end;
- PyObject *errorHandler = NULL;
- PyObject *exc = NULL;
- const char *encoding = "decimal";
- const char *reason = "invalid decimal Unicode string";
- /* the following variable is used for caching string comparisons
- * -1=not initialized, 0=unknown, 1=strict, 2=replace, 3=ignore, 4=xmlcharrefreplace */
- int known_errorHandler = -1;
-
- if (output == NULL) {
- PyErr_BadArgument();
- return -1;
- }
-
- p = s;
- end = s + length;
- while (p < end) {
- register Py_UNICODE ch = *p;
- int decimal;
- PyObject *repunicode;
- Py_ssize_t repsize;
- Py_ssize_t newpos;
- Py_UNICODE *uni2;
- Py_UNICODE *collstart;
- Py_UNICODE *collend;
-
- if (Py_UNICODE_ISSPACE(ch)) {
- *output++ = ' ';
- ++p;
- continue;
- }
- decimal = Py_UNICODE_TODECIMAL(ch);
- if (decimal >= 0) {
- *output++ = '0' + decimal;
- ++p;
- continue;
- }
- if (0 < ch && ch < 256) {
- *output++ = (char)ch;
- ++p;
- continue;
- }
- /* All other characters are considered unencodable */
- collstart = p;
- collend = p+1;
- while (collend < end) {
- if ((0 < *collend && *collend < 256) ||
- !Py_UNICODE_ISSPACE(*collend) ||
- Py_UNICODE_TODECIMAL(*collend))
- break;
- }
- /* cache callback name lookup
- * (if not done yet, i.e. it's the first error) */
- if (known_errorHandler==-1) {
- if ((errors==NULL) || (!strcmp(errors, "strict")))
- known_errorHandler = 1;
- else if (!strcmp(errors, "replace"))
- known_errorHandler = 2;
- else if (!strcmp(errors, "ignore"))
- known_errorHandler = 3;
- else if (!strcmp(errors, "xmlcharrefreplace"))
- known_errorHandler = 4;
- else
- known_errorHandler = 0;
- }
- switch (known_errorHandler) {
- case 1: /* strict */
- raise_encode_exception(&exc, encoding, s, length, collstart-s, collend-s, reason);
- goto onError;
- case 2: /* replace */
- for (p = collstart; p < collend; ++p)
- *output++ = '?';
- /* fall through */
- case 3: /* ignore */
- p = collend;
- break;
- case 4: /* xmlcharrefreplace */
- /* generate replacement (temporarily (mis)uses p) */
- for (p = collstart; p < collend; ++p)
- output += sprintf(output, "&#%d;", (int)*p);
- p = collend;
- break;
- default:
- repunicode = unicode_encode_call_errorhandler(errors, &errorHandler,
- encoding, reason, s, length, &exc,
- collstart-s, collend-s, &newpos);
- if (repunicode == NULL)
- goto onError;
- /* generate replacement */
- repsize = PyUnicode_GET_SIZE(repunicode);
- for (uni2 = PyUnicode_AS_UNICODE(repunicode); repsize-->0; ++uni2) {
- Py_UNICODE ch = *uni2;
- if (Py_UNICODE_ISSPACE(ch))
- *output++ = ' ';
- else {
- decimal = Py_UNICODE_TODECIMAL(ch);
- if (decimal >= 0)
- *output++ = '0' + decimal;
- else if (0 < ch && ch < 256)
- *output++ = (char)ch;
- else {
- Py_DECREF(repunicode);
- raise_encode_exception(&exc, encoding,
- s, length, collstart-s, collend-s, reason);
- goto onError;
- }
- }
- }
- p = s + newpos;
- Py_DECREF(repunicode);
- }
- }
- /* 0-terminate the output string */
- *output++ = '\0';
- Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
- return 0;
-
- onError:
- Py_XDECREF(exc);
- Py_XDECREF(errorHandler);
- return -1;
-}
-
-/* --- Helpers ------------------------------------------------------------ */
-
-#define STRINGLIB_CHAR Py_UNICODE
-
-#define STRINGLIB_LEN PyUnicode_GET_SIZE
-#define STRINGLIB_NEW PyUnicode_FromUnicode
-#define STRINGLIB_STR PyUnicode_AS_UNICODE
-
-Py_LOCAL_INLINE(int)
-STRINGLIB_CMP(const Py_UNICODE* str, const Py_UNICODE* other, Py_ssize_t len)
-{
- if (str[0] != other[0])
- return 1;
- return memcmp((void*) str, (void*) other, len * sizeof(Py_UNICODE));
-}
-
-#define STRINGLIB_EMPTY unicode_empty
-
-#include "stringlib/fastsearch.h"
-
-#include "stringlib/count.h"
-#include "stringlib/find.h"
-#include "stringlib/partition.h"
-
-/* helper macro to fixup start/end slice values */
-#define FIX_START_END(obj) \
- if (start < 0) \
- start += (obj)->length; \
- if (start < 0) \
- start = 0; \
- if (end > (obj)->length) \
- end = (obj)->length; \
- if (end < 0) \
- end += (obj)->length; \
- if (end < 0) \
- end = 0;
-
-Py_ssize_t PyUnicode_Count(PyObject *str,
- PyObject *substr,
- Py_ssize_t start,
- Py_ssize_t end)
-{
- Py_ssize_t result;
- PyUnicodeObject* str_obj;
- PyUnicodeObject* sub_obj;
-
- str_obj = (PyUnicodeObject*) PyUnicode_FromObject(str);
- if (!str_obj)
- return -1;
- sub_obj = (PyUnicodeObject*) PyUnicode_FromObject(substr);
- if (!sub_obj) {
- Py_DECREF(str_obj);
- return -1;
- }
-
- FIX_START_END(str_obj);
-
- result = stringlib_count(
- str_obj->str + start, end - start, sub_obj->str, sub_obj->length
- );
-
- Py_DECREF(sub_obj);
- Py_DECREF(str_obj);
-
- return result;
-}
-
-Py_ssize_t PyUnicode_Find(PyObject *str,
- PyObject *sub,
- Py_ssize_t start,
- Py_ssize_t end,
- int direction)
-{
- Py_ssize_t result;
-
- str = PyUnicode_FromObject(str);
- if (!str)
- return -2;
- sub = PyUnicode_FromObject(sub);
- if (!sub) {
- Py_DECREF(str);
- return -2;
- }
-
- if (direction > 0)
- result = stringlib_find_slice(
- PyUnicode_AS_UNICODE(str), PyUnicode_GET_SIZE(str),
- PyUnicode_AS_UNICODE(sub), PyUnicode_GET_SIZE(sub),
- start, end
- );
- else
- result = stringlib_rfind_slice(
- PyUnicode_AS_UNICODE(str), PyUnicode_GET_SIZE(str),
- PyUnicode_AS_UNICODE(sub), PyUnicode_GET_SIZE(sub),
- start, end
- );
-
- Py_DECREF(str);
- Py_DECREF(sub);
-
- return result;
-}
-
-static
-int tailmatch(PyUnicodeObject *self,
- PyUnicodeObject *substring,
- Py_ssize_t start,
- Py_ssize_t end,
- int direction)
-{
- if (substring->length == 0)
- return 1;
-
- FIX_START_END(self);
-
- end -= substring->length;
- if (end < start)
- return 0;
-
- if (direction > 0) {
- if (Py_UNICODE_MATCH(self, end, substring))
- return 1;
- } else {
- if (Py_UNICODE_MATCH(self, start, substring))
- return 1;
- }
-
- return 0;
-}
-
-Py_ssize_t PyUnicode_Tailmatch(PyObject *str,
- PyObject *substr,
- Py_ssize_t start,
- Py_ssize_t end,
- int direction)
-{
- Py_ssize_t result;
-
- str = PyUnicode_FromObject(str);
- if (str == NULL)
- return -1;
- substr = PyUnicode_FromObject(substr);
- if (substr == NULL) {
- Py_DECREF(str);
- return -1;
- }
-
- result = tailmatch((PyUnicodeObject *)str,
- (PyUnicodeObject *)substr,
- start, end, direction);
- Py_DECREF(str);
- Py_DECREF(substr);
- return result;
-}
-
-/* Apply fixfct filter to the Unicode object self and return a
- reference to the modified object */
-
-static
-PyObject *fixup(PyUnicodeObject *self,
- int (*fixfct)(PyUnicodeObject *s))
-{
-
- PyUnicodeObject *u;
-
- u = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, self->length);
- if (u == NULL)
- return NULL;
-
- Py_UNICODE_COPY(u->str, self->str, self->length);
-
- if (!fixfct(u) && PyUnicode_CheckExact(self)) {
- /* fixfct should return TRUE if it modified the buffer. If
- FALSE, return a reference to the original buffer instead
- (to save space, not time) */
- Py_INCREF(self);
- Py_DECREF(u);
- return (PyObject*) self;
- }
- return (PyObject*) u;
-}
-
-static
-int fixupper(PyUnicodeObject *self)
-{
- Py_ssize_t len = self->length;
- Py_UNICODE *s = self->str;
- int status = 0;
-
- while (len-- > 0) {
- register Py_UNICODE ch;
-
- ch = Py_UNICODE_TOUPPER(*s);
- if (ch != *s) {
- status = 1;
- *s = ch;
- }
- s++;
- }
-
- return status;
-}
-
-static
-int fixlower(PyUnicodeObject *self)
-{
- Py_ssize_t len = self->length;
- Py_UNICODE *s = self->str;
- int status = 0;
-
- while (len-- > 0) {
- register Py_UNICODE ch;
-
- ch = Py_UNICODE_TOLOWER(*s);
- if (ch != *s) {
- status = 1;
- *s = ch;
- }
- s++;
- }
-
- return status;
-}
-
-static
-int fixswapcase(PyUnicodeObject *self)
-{
- Py_ssize_t len = self->length;
- Py_UNICODE *s = self->str;
- int status = 0;
-
- while (len-- > 0) {
- if (Py_UNICODE_ISUPPER(*s)) {
- *s = Py_UNICODE_TOLOWER(*s);
- status = 1;
- } else if (Py_UNICODE_ISLOWER(*s)) {
- *s = Py_UNICODE_TOUPPER(*s);
- status = 1;
- }
- s++;
- }
-
- return status;
-}
-
-static
-int fixcapitalize(PyUnicodeObject *self)
-{
- Py_ssize_t len = self->length;
- Py_UNICODE *s = self->str;
- int status = 0;
-
- if (len == 0)
- return 0;
- if (Py_UNICODE_ISLOWER(*s)) {
- *s = Py_UNICODE_TOUPPER(*s);
- status = 1;
- }
- s++;
- while (--len > 0) {
- if (Py_UNICODE_ISUPPER(*s)) {
- *s = Py_UNICODE_TOLOWER(*s);
- status = 1;
- }
- s++;
- }
- return status;
-}
-
-static
-int fixtitle(PyUnicodeObject *self)
-{
- register Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register Py_UNICODE *e;
- int previous_is_cased;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1) {
- Py_UNICODE ch = Py_UNICODE_TOTITLE(*p);
- if (*p != ch) {
- *p = ch;
- return 1;
- }
- else
- return 0;
- }
-
- e = p + PyUnicode_GET_SIZE(self);
- previous_is_cased = 0;
- for (; p < e; p++) {
- register const Py_UNICODE ch = *p;
-
- if (previous_is_cased)
- *p = Py_UNICODE_TOLOWER(ch);
- else
- *p = Py_UNICODE_TOTITLE(ch);
-
- if (Py_UNICODE_ISLOWER(ch) ||
- Py_UNICODE_ISUPPER(ch) ||
- Py_UNICODE_ISTITLE(ch))
- previous_is_cased = 1;
- else
- previous_is_cased = 0;
- }
- return 1;
-}
-
-PyObject *
-PyUnicode_Join(PyObject *separator, PyObject *seq)
-{
- PyObject *internal_separator = NULL;
- const Py_UNICODE blank = ' ';
- const Py_UNICODE *sep = &blank;
- Py_ssize_t seplen = 1;
- PyUnicodeObject *res = NULL; /* the result */
- Py_ssize_t res_alloc = 100; /* # allocated bytes for string in res */
- Py_ssize_t res_used; /* # used bytes */
- Py_UNICODE *res_p; /* pointer to free byte in res's string area */
- PyObject *fseq; /* PySequence_Fast(seq) */
- Py_ssize_t seqlen; /* len(fseq) -- number of items in sequence */
- PyObject *item;
- Py_ssize_t i;
-
- fseq = PySequence_Fast(seq, "");
- if (fseq == NULL) {
- return NULL;
- }
-
- /* Grrrr. A codec may be invoked to convert str objects to
- * Unicode, and so it's possible to call back into Python code
- * during PyUnicode_FromObject(), and so it's possible for a sick
- * codec to change the size of fseq (if seq is a list). Therefore
- * we have to keep refetching the size -- can't assume seqlen
- * is invariant.
- */
- seqlen = PySequence_Fast_GET_SIZE(fseq);
- /* If empty sequence, return u"". */
- if (seqlen == 0) {
- res = _PyUnicode_New(0); /* empty sequence; return u"" */
- goto Done;
- }
- /* If singleton sequence with an exact Unicode, return that. */
- if (seqlen == 1) {
- item = PySequence_Fast_GET_ITEM(fseq, 0);
- if (PyUnicode_CheckExact(item)) {
- Py_INCREF(item);
- res = (PyUnicodeObject *)item;
- goto Done;
- }
- }
-
- /* At least two items to join, or one that isn't exact Unicode. */
- if (seqlen > 1) {
- /* Set up sep and seplen -- they're needed. */
- if (separator == NULL) {
- sep = &blank;
- seplen = 1;
- }
- else {
- internal_separator = PyUnicode_FromObject(separator);
- if (internal_separator == NULL)
- goto onError;
- sep = PyUnicode_AS_UNICODE(internal_separator);
- seplen = PyUnicode_GET_SIZE(internal_separator);
- /* In case PyUnicode_FromObject() mutated seq. */
- seqlen = PySequence_Fast_GET_SIZE(fseq);
- }
- }
-
- /* Get space. */
- res = _PyUnicode_New(res_alloc);
- if (res == NULL)
- goto onError;
- res_p = PyUnicode_AS_UNICODE(res);
- res_used = 0;
-
- for (i = 0; i < seqlen; ++i) {
- Py_ssize_t itemlen;
- Py_ssize_t new_res_used;
-
- item = PySequence_Fast_GET_ITEM(fseq, i);
- /* Convert item to Unicode. */
- if (! PyUnicode_Check(item) && ! PyString_Check(item)) {
- PyErr_Format(PyExc_TypeError,
- "sequence item %zd: expected string or Unicode,"
- " %.80s found",
- i, item->ob_type->tp_name);
- goto onError;
- }
- item = PyUnicode_FromObject(item);
- if (item == NULL)
- goto onError;
- /* We own a reference to item from here on. */
-
- /* In case PyUnicode_FromObject() mutated seq. */
- seqlen = PySequence_Fast_GET_SIZE(fseq);
-
- /* Make sure we have enough space for the separator and the item. */
- itemlen = PyUnicode_GET_SIZE(item);
- new_res_used = res_used + itemlen;
- if (new_res_used < 0)
- goto Overflow;
- if (i < seqlen - 1) {
- new_res_used += seplen;
- if (new_res_used < 0)
- goto Overflow;
- }
- if (new_res_used > res_alloc) {
- /* double allocated size until it's big enough */
- do {
- res_alloc += res_alloc;
- if (res_alloc <= 0)
- goto Overflow;
- } while (new_res_used > res_alloc);
- if (_PyUnicode_Resize(&res, res_alloc) < 0) {
- Py_DECREF(item);
- goto onError;
- }
- res_p = PyUnicode_AS_UNICODE(res) + res_used;
- }
-
- /* Copy item, and maybe the separator. */
- Py_UNICODE_COPY(res_p, PyUnicode_AS_UNICODE(item), itemlen);
- res_p += itemlen;
- if (i < seqlen - 1) {
- Py_UNICODE_COPY(res_p, sep, seplen);
- res_p += seplen;
- }
- Py_DECREF(item);
- res_used = new_res_used;
- }
-
- /* Shrink res to match the used area; this probably can't fail,
- * but it's cheap to check.
- */
- if (_PyUnicode_Resize(&res, res_used) < 0)
- goto onError;
-
- Done:
- Py_XDECREF(internal_separator);
- Py_DECREF(fseq);
- return (PyObject *)res;
-
- Overflow:
- PyErr_SetString(PyExc_OverflowError,
- "join() result is too long for a Python string");
- Py_DECREF(item);
- /* fall through */
-
- onError:
- Py_XDECREF(internal_separator);
- Py_DECREF(fseq);
- Py_XDECREF(res);
- return NULL;
-}
-
-static
-PyUnicodeObject *pad(PyUnicodeObject *self,
- Py_ssize_t left,
- Py_ssize_t right,
- Py_UNICODE fill)
-{
- PyUnicodeObject *u;
-
- if (left < 0)
- left = 0;
- if (right < 0)
- right = 0;
-
- if (left == 0 && right == 0 && PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return self;
- }
-
- u = _PyUnicode_New(left + self->length + right);
- if (u) {
- if (left)
- Py_UNICODE_FILL(u->str, fill, left);
- Py_UNICODE_COPY(u->str + left, self->str, self->length);
- if (right)
- Py_UNICODE_FILL(u->str + left + self->length, fill, right);
- }
-
- return u;
-}
-
-#define SPLIT_APPEND(data, left, right) \
- str = PyUnicode_FromUnicode((data) + (left), (right) - (left)); \
- if (!str) \
- goto onError; \
- if (PyList_Append(list, str)) { \
- Py_DECREF(str); \
- goto onError; \
- } \
- else \
- Py_DECREF(str);
-
-static
-PyObject *split_whitespace(PyUnicodeObject *self,
- PyObject *list,
- Py_ssize_t maxcount)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len = self->length;
- PyObject *str;
-
- for (i = j = 0; i < len; ) {
- /* find a token */
- while (i < len && Py_UNICODE_ISSPACE(self->str[i]))
- i++;
- j = i;
- while (i < len && !Py_UNICODE_ISSPACE(self->str[i]))
- i++;
- if (j < i) {
- if (maxcount-- <= 0)
- break;
- SPLIT_APPEND(self->str, j, i);
- while (i < len && Py_UNICODE_ISSPACE(self->str[i]))
- i++;
- j = i;
- }
- }
- if (j < len) {
- SPLIT_APPEND(self->str, j, len);
- }
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-PyObject *PyUnicode_Splitlines(PyObject *string,
- int keepends)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len;
- PyObject *list;
- PyObject *str;
- Py_UNICODE *data;
-
- string = PyUnicode_FromObject(string);
- if (string == NULL)
- return NULL;
- data = PyUnicode_AS_UNICODE(string);
- len = PyUnicode_GET_SIZE(string);
-
- list = PyList_New(0);
- if (!list)
- goto onError;
-
- for (i = j = 0; i < len; ) {
- Py_ssize_t eol;
-
- /* Find a line and append it */
- while (i < len && !BLOOM_LINEBREAK(data[i]))
- i++;
-
- /* Skip the line break reading CRLF as one line break */
- eol = i;
- if (i < len) {
- if (data[i] == '\r' && i + 1 < len &&
- data[i+1] == '\n')
- i += 2;
- else
- i++;
- if (keepends)
- eol = i;
- }
- SPLIT_APPEND(data, j, eol);
- j = i;
- }
- if (j < len) {
- SPLIT_APPEND(data, j, len);
- }
-
- Py_DECREF(string);
- return list;
-
- onError:
- Py_XDECREF(list);
- Py_DECREF(string);
- return NULL;
-}
-
-static
-PyObject *split_char(PyUnicodeObject *self,
- PyObject *list,
- Py_UNICODE ch,
- Py_ssize_t maxcount)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len = self->length;
- PyObject *str;
-
- for (i = j = 0; i < len; ) {
- if (self->str[i] == ch) {
- if (maxcount-- <= 0)
- break;
- SPLIT_APPEND(self->str, j, i);
- i = j = i + 1;
- } else
- i++;
- }
- if (j <= len) {
- SPLIT_APPEND(self->str, j, len);
- }
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-static
-PyObject *split_substring(PyUnicodeObject *self,
- PyObject *list,
- PyUnicodeObject *substring,
- Py_ssize_t maxcount)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len = self->length;
- Py_ssize_t sublen = substring->length;
- PyObject *str;
-
- for (i = j = 0; i <= len - sublen; ) {
- if (Py_UNICODE_MATCH(self, i, substring)) {
- if (maxcount-- <= 0)
- break;
- SPLIT_APPEND(self->str, j, i);
- i = j = i + sublen;
- } else
- i++;
- }
- if (j <= len) {
- SPLIT_APPEND(self->str, j, len);
- }
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-static
-PyObject *rsplit_whitespace(PyUnicodeObject *self,
- PyObject *list,
- Py_ssize_t maxcount)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len = self->length;
- PyObject *str;
-
- for (i = j = len - 1; i >= 0; ) {
- /* find a token */
- while (i >= 0 && Py_UNICODE_ISSPACE(self->str[i]))
- i--;
- j = i;
- while (i >= 0 && !Py_UNICODE_ISSPACE(self->str[i]))
- i--;
- if (j > i) {
- if (maxcount-- <= 0)
- break;
- SPLIT_APPEND(self->str, i + 1, j + 1);
- while (i >= 0 && Py_UNICODE_ISSPACE(self->str[i]))
- i--;
- j = i;
- }
- }
- if (j >= 0) {
- SPLIT_APPEND(self->str, 0, j + 1);
- }
- if (PyList_Reverse(list) < 0)
- goto onError;
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-static
-PyObject *rsplit_char(PyUnicodeObject *self,
- PyObject *list,
- Py_UNICODE ch,
- Py_ssize_t maxcount)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len = self->length;
- PyObject *str;
-
- for (i = j = len - 1; i >= 0; ) {
- if (self->str[i] == ch) {
- if (maxcount-- <= 0)
- break;
- SPLIT_APPEND(self->str, i + 1, j + 1);
- j = i = i - 1;
- } else
- i--;
- }
- if (j >= -1) {
- SPLIT_APPEND(self->str, 0, j + 1);
- }
- if (PyList_Reverse(list) < 0)
- goto onError;
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-static
-PyObject *rsplit_substring(PyUnicodeObject *self,
- PyObject *list,
- PyUnicodeObject *substring,
- Py_ssize_t maxcount)
-{
- register Py_ssize_t i;
- register Py_ssize_t j;
- Py_ssize_t len = self->length;
- Py_ssize_t sublen = substring->length;
- PyObject *str;
-
- for (i = len - sublen, j = len; i >= 0; ) {
- if (Py_UNICODE_MATCH(self, i, substring)) {
- if (maxcount-- <= 0)
- break;
- SPLIT_APPEND(self->str, i + sublen, j);
- j = i;
- i -= sublen;
- } else
- i--;
- }
- if (j >= 0) {
- SPLIT_APPEND(self->str, 0, j);
- }
- if (PyList_Reverse(list) < 0)
- goto onError;
- return list;
-
- onError:
- Py_DECREF(list);
- return NULL;
-}
-
-#undef SPLIT_APPEND
-
-static
-PyObject *split(PyUnicodeObject *self,
- PyUnicodeObject *substring,
- Py_ssize_t maxcount)
-{
- PyObject *list;
-
- if (maxcount < 0)
- maxcount = PY_SSIZE_T_MAX;
-
- list = PyList_New(0);
- if (!list)
- return NULL;
-
- if (substring == NULL)
- return split_whitespace(self,list,maxcount);
-
- else if (substring->length == 1)
- return split_char(self,list,substring->str[0],maxcount);
-
- else if (substring->length == 0) {
- Py_DECREF(list);
- PyErr_SetString(PyExc_ValueError, "empty separator");
- return NULL;
- }
- else
- return split_substring(self,list,substring,maxcount);
-}
-
-static
-PyObject *rsplit(PyUnicodeObject *self,
- PyUnicodeObject *substring,
- Py_ssize_t maxcount)
-{
- PyObject *list;
-
- if (maxcount < 0)
- maxcount = PY_SSIZE_T_MAX;
-
- list = PyList_New(0);
- if (!list)
- return NULL;
-
- if (substring == NULL)
- return rsplit_whitespace(self,list,maxcount);
-
- else if (substring->length == 1)
- return rsplit_char(self,list,substring->str[0],maxcount);
-
- else if (substring->length == 0) {
- Py_DECREF(list);
- PyErr_SetString(PyExc_ValueError, "empty separator");
- return NULL;
- }
- else
- return rsplit_substring(self,list,substring,maxcount);
-}
-
-static
-PyObject *replace(PyUnicodeObject *self,
- PyUnicodeObject *str1,
- PyUnicodeObject *str2,
- Py_ssize_t maxcount)
-{
- PyUnicodeObject *u;
-
- if (maxcount < 0)
- maxcount = PY_SSIZE_T_MAX;
-
- if (str1->length == str2->length) {
- /* same length */
- Py_ssize_t i;
- if (str1->length == 1) {
- /* replace characters */
- Py_UNICODE u1, u2;
- if (!findchar(self->str, self->length, str1->str[0]))
- goto nothing;
- u = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, self->length);
- if (!u)
- return NULL;
- Py_UNICODE_COPY(u->str, self->str, self->length);
- u1 = str1->str[0];
- u2 = str2->str[0];
- for (i = 0; i < u->length; i++)
- if (u->str[i] == u1) {
- if (--maxcount < 0)
- break;
- u->str[i] = u2;
- }
- } else {
- i = fastsearch(
- self->str, self->length, str1->str, str1->length, FAST_SEARCH
- );
- if (i < 0)
- goto nothing;
- u = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, self->length);
- if (!u)
- return NULL;
- Py_UNICODE_COPY(u->str, self->str, self->length);
- while (i <= self->length - str1->length)
- if (Py_UNICODE_MATCH(self, i, str1)) {
- if (--maxcount < 0)
- break;
- Py_UNICODE_COPY(u->str+i, str2->str, str2->length);
- i += str1->length;
- } else
- i++;
- }
- } else {
-
- Py_ssize_t n, i, j, e;
- Py_ssize_t product, new_size, delta;
- Py_UNICODE *p;
-
- /* replace strings */
- n = stringlib_count(self->str, self->length, str1->str, str1->length);
- if (n > maxcount)
- n = maxcount;
- if (n == 0)
- goto nothing;
- /* new_size = self->length + n * (str2->length - str1->length)); */
- delta = (str2->length - str1->length);
- if (delta == 0) {
- new_size = self->length;
- } else {
- product = n * (str2->length - str1->length);
- if ((product / (str2->length - str1->length)) != n) {
- PyErr_SetString(PyExc_OverflowError,
- "replace string is too long");
- return NULL;
- }
- new_size = self->length + product;
- if (new_size < 0) {
- PyErr_SetString(PyExc_OverflowError,
- "replace string is too long");
- return NULL;
- }
- }
- u = _PyUnicode_New(new_size);
- if (!u)
- return NULL;
- i = 0;
- p = u->str;
- e = self->length - str1->length;
- if (str1->length > 0) {
- while (n-- > 0) {
- /* look for next match */
- j = i;
- while (j <= e) {
- if (Py_UNICODE_MATCH(self, j, str1))
- break;
- j++;
- }
- if (j > i) {
- if (j > e)
- break;
- /* copy unchanged part [i:j] */
- Py_UNICODE_COPY(p, self->str+i, j-i);
- p += j - i;
- }
- /* copy substitution string */
- if (str2->length > 0) {
- Py_UNICODE_COPY(p, str2->str, str2->length);
- p += str2->length;
- }
- i = j + str1->length;
- }
- if (i < self->length)
- /* copy tail [i:] */
- Py_UNICODE_COPY(p, self->str+i, self->length-i);
- } else {
- /* interleave */
- while (n > 0) {
- Py_UNICODE_COPY(p, str2->str, str2->length);
- p += str2->length;
- if (--n <= 0)
- break;
- *p++ = self->str[i++];
- }
- Py_UNICODE_COPY(p, self->str+i, self->length-i);
- }
- }
- return (PyObject *) u;
-
-nothing:
- /* nothing to replace; return original string (when possible) */
- if (PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject *) self;
- }
- return PyUnicode_FromUnicode(self->str, self->length);
-}
-
-/* --- Unicode Object Methods --------------------------------------------- */
-
-PyDoc_STRVAR(title__doc__,
-"S.title() -> unicode\n\
-\n\
-Return a titlecased version of S, i.e. words start with title case\n\
-characters, all remaining cased characters have lower case.");
-
-static PyObject*
-unicode_title(PyUnicodeObject *self)
-{
- return fixup(self, fixtitle);
-}
-
-PyDoc_STRVAR(capitalize__doc__,
-"S.capitalize() -> unicode\n\
-\n\
-Return a capitalized version of S, i.e. make the first character\n\
-have upper case.");
-
-static PyObject*
-unicode_capitalize(PyUnicodeObject *self)
-{
- return fixup(self, fixcapitalize);
-}
-
-#if 0
-PyDoc_STRVAR(capwords__doc__,
-"S.capwords() -> unicode\n\
-\n\
-Apply .capitalize() to all words in S and return the result with\n\
-normalized whitespace (all whitespace strings are replaced by ' ').");
-
-static PyObject*
-unicode_capwords(PyUnicodeObject *self)
-{
- PyObject *list;
- PyObject *item;
- Py_ssize_t i;
-
- /* Split into words */
- list = split(self, NULL, -1);
- if (!list)
- return NULL;
-
- /* Capitalize each word */
- for (i = 0; i < PyList_GET_SIZE(list); i++) {
- item = fixup((PyUnicodeObject *)PyList_GET_ITEM(list, i),
- fixcapitalize);
- if (item == NULL)
- goto onError;
- Py_DECREF(PyList_GET_ITEM(list, i));
- PyList_SET_ITEM(list, i, item);
- }
-
- /* Join the words to form a new string */
- item = PyUnicode_Join(NULL, list);
-
-onError:
- Py_DECREF(list);
- return (PyObject *)item;
-}
-#endif
-
-/* Argument converter. Coerces to a single unicode character */
-
-static int
-convert_uc(PyObject *obj, void *addr)
-{
- Py_UNICODE *fillcharloc = (Py_UNICODE *)addr;
- PyObject *uniobj;
- Py_UNICODE *unistr;
-
- uniobj = PyUnicode_FromObject(obj);
- if (uniobj == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "The fill character cannot be converted to Unicode");
- return 0;
- }
- if (PyUnicode_GET_SIZE(uniobj) != 1) {
- PyErr_SetString(PyExc_TypeError,
- "The fill character must be exactly one character long");
- Py_DECREF(uniobj);
- return 0;
- }
- unistr = PyUnicode_AS_UNICODE(uniobj);
- *fillcharloc = unistr[0];
- Py_DECREF(uniobj);
- return 1;
-}
-
-PyDoc_STRVAR(center__doc__,
-"S.center(width[, fillchar]) -> unicode\n\
-\n\
-Return S centered in a Unicode string of length width. Padding is\n\
-done using the specified fill character (default is a space)");
-
-static PyObject *
-unicode_center(PyUnicodeObject *self, PyObject *args)
-{
- Py_ssize_t marg, left;
- Py_ssize_t width;
- Py_UNICODE fillchar = ' ';
-
- if (!PyArg_ParseTuple(args, "n|O&:center", &width, convert_uc, &fillchar))
- return NULL;
-
- if (self->length >= width && PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
-
- marg = width - self->length;
- left = marg / 2 + (marg & width & 1);
-
- return (PyObject*) pad(self, left, marg - left, fillchar);
-}
-
-#if 0
-
-/* This code should go into some future Unicode collation support
- module. The basic comparison should compare ordinals on a naive
- basis (this is what Java does and thus JPython too). */
-
-/* speedy UTF-16 code point order comparison */
-/* gleaned from: */
-/* http://www-4.ibm.com/software/developer/library/utf16.html?dwzone=unicode */
-
-static short utf16Fixup[32] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0x2000, -0x800, -0x800, -0x800, -0x800
-};
-
-static int
-unicode_compare(PyUnicodeObject *str1, PyUnicodeObject *str2)
-{
- Py_ssize_t len1, len2;
-
- Py_UNICODE *s1 = str1->str;
- Py_UNICODE *s2 = str2->str;
-
- len1 = str1->length;
- len2 = str2->length;
-
- while (len1 > 0 && len2 > 0) {
- Py_UNICODE c1, c2;
-
- c1 = *s1++;
- c2 = *s2++;
-
- if (c1 > (1<<11) * 26)
- c1 += utf16Fixup[c1>>11];
- if (c2 > (1<<11) * 26)
- c2 += utf16Fixup[c2>>11];
- /* now c1 and c2 are in UTF-32-compatible order */
-
- if (c1 != c2)
- return (c1 < c2) ? -1 : 1;
-
- len1--; len2--;
- }
-
- return (len1 < len2) ? -1 : (len1 != len2);
-}
-
-#else
-
-static int
-unicode_compare(PyUnicodeObject *str1, PyUnicodeObject *str2)
-{
- register Py_ssize_t len1, len2;
-
- Py_UNICODE *s1 = str1->str;
- Py_UNICODE *s2 = str2->str;
-
- len1 = str1->length;
- len2 = str2->length;
-
- while (len1 > 0 && len2 > 0) {
- Py_UNICODE c1, c2;
-
- c1 = *s1++;
- c2 = *s2++;
-
- if (c1 != c2)
- return (c1 < c2) ? -1 : 1;
-
- len1--; len2--;
- }
-
- return (len1 < len2) ? -1 : (len1 != len2);
-}
-
-#endif
-
-int PyUnicode_Compare(PyObject *left,
- PyObject *right)
-{
- PyUnicodeObject *u = NULL, *v = NULL;
- int result;
-
- /* Coerce the two arguments */
- u = (PyUnicodeObject *)PyUnicode_FromObject(left);
- if (u == NULL)
- goto onError;
- v = (PyUnicodeObject *)PyUnicode_FromObject(right);
- if (v == NULL)
- goto onError;
-
- /* Shortcut for empty or interned objects */
- if (v == u) {
- Py_DECREF(u);
- Py_DECREF(v);
- return 0;
- }
-
- result = unicode_compare(u, v);
-
- Py_DECREF(u);
- Py_DECREF(v);
- return result;
-
-onError:
- Py_XDECREF(u);
- Py_XDECREF(v);
- return -1;
-}
-
-PyObject *PyUnicode_RichCompare(PyObject *left,
- PyObject *right,
- int op)
-{
- int result;
-
- result = PyUnicode_Compare(left, right);
- if (result == -1 && PyErr_Occurred())
- goto onError;
-
- /* Convert the return value to a Boolean */
- switch (op) {
- case Py_EQ:
- result = (result == 0);
- break;
- case Py_NE:
- result = (result != 0);
- break;
- case Py_LE:
- result = (result <= 0);
- break;
- case Py_GE:
- result = (result >= 0);
- break;
- case Py_LT:
- result = (result == -1);
- break;
- case Py_GT:
- result = (result == 1);
- break;
- }
- return PyBool_FromLong(result);
-
- onError:
-
- /* Standard case
-
- Type errors mean that PyUnicode_FromObject() could not convert
- one of the arguments (usually the right hand side) to Unicode,
- ie. we can't handle the comparison request. However, it is
- possible that the other object knows a comparison method, which
- is why we return Py_NotImplemented to give the other object a
- chance.
-
- */
- if (PyErr_ExceptionMatches(PyExc_TypeError)) {
- PyErr_Clear();
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- if (op != Py_EQ && op != Py_NE)
- return NULL;
-
- /* Equality comparison.
-
- This is a special case: we silence any PyExc_UnicodeDecodeError
- and instead turn it into a PyErr_UnicodeWarning.
-
- */
- if (!PyErr_ExceptionMatches(PyExc_UnicodeDecodeError))
- return NULL;
- PyErr_Clear();
- if (PyErr_Warn(PyExc_UnicodeWarning,
- (op == Py_EQ) ?
- "Unicode equal comparison "
- "failed to convert both arguments to Unicode - "
- "interpreting them as being unequal" :
- "Unicode unequal comparison "
- "failed to convert both arguments to Unicode - "
- "interpreting them as being unequal"
- ) < 0)
- return NULL;
- result = (op == Py_NE);
- return PyBool_FromLong(result);
-}
-
-int PyUnicode_Contains(PyObject *container,
- PyObject *element)
-{
- PyObject *str, *sub;
- int result;
-
- /* Coerce the two arguments */
- sub = PyUnicode_FromObject(element);
- if (!sub) {
- PyErr_SetString(PyExc_TypeError,
- "'in <string>' requires string as left operand");
- return -1;
- }
-
- str = PyUnicode_FromObject(container);
- if (!str) {
- Py_DECREF(sub);
- return -1;
- }
-
- result = stringlib_contains_obj(str, sub);
-
- Py_DECREF(str);
- Py_DECREF(sub);
-
- return result;
-}
-
-/* Concat to string or Unicode object giving a new Unicode object. */
-
-PyObject *PyUnicode_Concat(PyObject *left,
- PyObject *right)
-{
- PyUnicodeObject *u = NULL, *v = NULL, *w;
-
- /* Coerce the two arguments */
- u = (PyUnicodeObject *)PyUnicode_FromObject(left);
- if (u == NULL)
- goto onError;
- v = (PyUnicodeObject *)PyUnicode_FromObject(right);
- if (v == NULL)
- goto onError;
-
- /* Shortcuts */
- if (v == unicode_empty) {
- Py_DECREF(v);
- return (PyObject *)u;
- }
- if (u == unicode_empty) {
- Py_DECREF(u);
- return (PyObject *)v;
- }
-
- /* Concat the two Unicode strings */
- w = _PyUnicode_New(u->length + v->length);
- if (w == NULL)
- goto onError;
- Py_UNICODE_COPY(w->str, u->str, u->length);
- Py_UNICODE_COPY(w->str + u->length, v->str, v->length);
-
- Py_DECREF(u);
- Py_DECREF(v);
- return (PyObject *)w;
-
-onError:
- Py_XDECREF(u);
- Py_XDECREF(v);
- return NULL;
-}
-
-PyDoc_STRVAR(count__doc__,
-"S.count(sub[, start[, end]]) -> int\n\
-\n\
-Return the number of non-overlapping occurrences of substring sub in\n\
-Unicode string S[start:end]. Optional arguments start and end are\n\
-interpreted as in slice notation.");
-
-static PyObject *
-unicode_count(PyUnicodeObject *self, PyObject *args)
-{
- PyUnicodeObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- PyObject *result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:count", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
-
- substring = (PyUnicodeObject *)PyUnicode_FromObject(
- (PyObject *)substring);
- if (substring == NULL)
- return NULL;
-
- FIX_START_END(self);
-
- result = PyInt_FromSsize_t(
- stringlib_count(self->str + start, end - start,
- substring->str, substring->length)
- );
-
- Py_DECREF(substring);
-
- return result;
-}
-
-PyDoc_STRVAR(encode__doc__,
-"S.encode([encoding[,errors]]) -> string or unicode\n\
-\n\
-Encodes S using the codec registered for encoding. encoding defaults\n\
-to the default encoding. errors may be given to set a different error\n\
-handling scheme. Default is 'strict' meaning that encoding errors raise\n\
-a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and\n\
-'xmlcharrefreplace' as well as any other name registered with\n\
-codecs.register_error that can handle UnicodeEncodeErrors.");
-
-static PyObject *
-unicode_encode(PyUnicodeObject *self, PyObject *args)
-{
- char *encoding = NULL;
- char *errors = NULL;
- PyObject *v;
-
- if (!PyArg_ParseTuple(args, "|ss:encode", &encoding, &errors))
- return NULL;
- v = PyUnicode_AsEncodedObject((PyObject *)self, encoding, errors);
- if (v == NULL)
- goto onError;
- if (!PyString_Check(v) && !PyUnicode_Check(v)) {
- PyErr_Format(PyExc_TypeError,
- "encoder did not return a string/unicode object "
- "(type=%.400s)",
- v->ob_type->tp_name);
- Py_DECREF(v);
- return NULL;
- }
- return v;
-
- onError:
- return NULL;
-}
-
-PyDoc_STRVAR(decode__doc__,
-"S.decode([encoding[,errors]]) -> string or unicode\n\
-\n\
-Decodes S using the codec registered for encoding. encoding defaults\n\
-to the default encoding. errors may be given to set a different error\n\
-handling scheme. Default is 'strict' meaning that encoding errors raise\n\
-a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'\n\
-as well as any other name registerd with codecs.register_error that is\n\
-able to handle UnicodeDecodeErrors.");
-
-static PyObject *
-unicode_decode(PyUnicodeObject *self, PyObject *args)
-{
- char *encoding = NULL;
- char *errors = NULL;
- PyObject *v;
-
- if (!PyArg_ParseTuple(args, "|ss:decode", &encoding, &errors))
- return NULL;
- v = PyUnicode_AsDecodedObject((PyObject *)self, encoding, errors);
- if (v == NULL)
- goto onError;
- if (!PyString_Check(v) && !PyUnicode_Check(v)) {
- PyErr_Format(PyExc_TypeError,
- "decoder did not return a string/unicode object "
- "(type=%.400s)",
- v->ob_type->tp_name);
- Py_DECREF(v);
- return NULL;
- }
- return v;
-
- onError:
- return NULL;
-}
-
-PyDoc_STRVAR(expandtabs__doc__,
-"S.expandtabs([tabsize]) -> unicode\n\
-\n\
-Return a copy of S where all tab characters are expanded using spaces.\n\
-If tabsize is not given, a tab size of 8 characters is assumed.");
-
-static PyObject*
-unicode_expandtabs(PyUnicodeObject *self, PyObject *args)
-{
- Py_UNICODE *e;
- Py_UNICODE *p;
- Py_UNICODE *q;
- Py_ssize_t i, j;
- PyUnicodeObject *u;
- int tabsize = 8;
-
- if (!PyArg_ParseTuple(args, "|i:expandtabs", &tabsize))
- return NULL;
-
- /* First pass: determine size of output string */
- i = j = 0;
- e = self->str + self->length;
- for (p = self->str; p < e; p++)
- if (*p == '\t') {
- if (tabsize > 0)
- j += tabsize - (j % tabsize);
- }
- else {
- j++;
- if (*p == '\n' || *p == '\r') {
- i += j;
- j = 0;
- }
- }
-
- /* Second pass: create output string and fill it */
- u = _PyUnicode_New(i + j);
- if (!u)
- return NULL;
-
- j = 0;
- q = u->str;
-
- for (p = self->str; p < e; p++)
- if (*p == '\t') {
- if (tabsize > 0) {
- i = tabsize - (j % tabsize);
- j += i;
- while (i--)
- *q++ = ' ';
- }
- }
- else {
- j++;
- *q++ = *p;
- if (*p == '\n' || *p == '\r')
- j = 0;
- }
-
- return (PyObject*) u;
-}
-
-PyDoc_STRVAR(find__doc__,
-"S.find(sub [,start [,end]]) -> int\n\
-\n\
-Return the lowest index in S where substring sub is found,\n\
-such that sub is contained within s[start,end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
-static PyObject *
-unicode_find(PyUnicodeObject *self, PyObject *args)
-{
- PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- Py_ssize_t result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:find", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
-
- result = stringlib_find_slice(
- PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),
- PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),
- start, end
- );
-
- Py_DECREF(substring);
-
- return PyInt_FromSsize_t(result);
-}
-
-static PyObject *
-unicode_getitem(PyUnicodeObject *self, Py_ssize_t index)
-{
- if (index < 0 || index >= self->length) {
- PyErr_SetString(PyExc_IndexError, "string index out of range");
- return NULL;
- }
-
- return (PyObject*) PyUnicode_FromUnicode(&self->str[index], 1);
-}
-
-static long
-unicode_hash(PyUnicodeObject *self)
-{
- /* Since Unicode objects compare equal to their ASCII string
- counterparts, they should use the individual character values
- as basis for their hash value. This is needed to assure that
- strings and Unicode objects behave in the same way as
- dictionary keys. */
-
- register Py_ssize_t len;
- register Py_UNICODE *p;
- register long x;
-
- if (self->hash != -1)
- return self->hash;
- len = PyUnicode_GET_SIZE(self);
- p = PyUnicode_AS_UNICODE(self);
- x = *p << 7;
- while (--len >= 0)
- x = (1000003*x) ^ *p++;
- x ^= PyUnicode_GET_SIZE(self);
- if (x == -1)
- x = -2;
- self->hash = x;
- return x;
-}
-
-PyDoc_STRVAR(index__doc__,
-"S.index(sub [,start [,end]]) -> int\n\
-\n\
-Like S.find() but raise ValueError when the substring is not found.");
-
-static PyObject *
-unicode_index(PyUnicodeObject *self, PyObject *args)
-{
- Py_ssize_t result;
- PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:index", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
-
- result = stringlib_find_slice(
- PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),
- PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),
- start, end
- );
-
- Py_DECREF(substring);
-
- if (result < 0) {
- PyErr_SetString(PyExc_ValueError, "substring not found");
- return NULL;
- }
-
- return PyInt_FromSsize_t(result);
-}
-
-PyDoc_STRVAR(islower__doc__,
-"S.islower() -> bool\n\
-\n\
-Return True if all cased characters in S are lowercase and there is\n\
-at least one cased character in S, False otherwise.");
-
-static PyObject*
-unicode_islower(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
- int cased;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1)
- return PyBool_FromLong(Py_UNICODE_ISLOWER(*p));
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- cased = 0;
- for (; p < e; p++) {
- register const Py_UNICODE ch = *p;
-
- if (Py_UNICODE_ISUPPER(ch) || Py_UNICODE_ISTITLE(ch))
- return PyBool_FromLong(0);
- else if (!cased && Py_UNICODE_ISLOWER(ch))
- cased = 1;
- }
- return PyBool_FromLong(cased);
-}
-
-PyDoc_STRVAR(isupper__doc__,
-"S.isupper() -> bool\n\
-\n\
-Return True if all cased characters in S are uppercase and there is\n\
-at least one cased character in S, False otherwise.");
-
-static PyObject*
-unicode_isupper(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
- int cased;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1)
- return PyBool_FromLong(Py_UNICODE_ISUPPER(*p) != 0);
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- cased = 0;
- for (; p < e; p++) {
- register const Py_UNICODE ch = *p;
-
- if (Py_UNICODE_ISLOWER(ch) || Py_UNICODE_ISTITLE(ch))
- return PyBool_FromLong(0);
- else if (!cased && Py_UNICODE_ISUPPER(ch))
- cased = 1;
- }
- return PyBool_FromLong(cased);
-}
-
-PyDoc_STRVAR(istitle__doc__,
-"S.istitle() -> bool\n\
-\n\
-Return True if S is a titlecased string and there is at least one\n\
-character in S, i.e. upper- and titlecase characters may only\n\
-follow uncased characters and lowercase characters only cased ones.\n\
-Return False otherwise.");
-
-static PyObject*
-unicode_istitle(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
- int cased, previous_is_cased;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1)
- return PyBool_FromLong((Py_UNICODE_ISTITLE(*p) != 0) ||
- (Py_UNICODE_ISUPPER(*p) != 0));
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- cased = 0;
- previous_is_cased = 0;
- for (; p < e; p++) {
- register const Py_UNICODE ch = *p;
-
- if (Py_UNICODE_ISUPPER(ch) || Py_UNICODE_ISTITLE(ch)) {
- if (previous_is_cased)
- return PyBool_FromLong(0);
- previous_is_cased = 1;
- cased = 1;
- }
- else if (Py_UNICODE_ISLOWER(ch)) {
- if (!previous_is_cased)
- return PyBool_FromLong(0);
- previous_is_cased = 1;
- cased = 1;
- }
- else
- previous_is_cased = 0;
- }
- return PyBool_FromLong(cased);
-}
-
-PyDoc_STRVAR(isspace__doc__,
-"S.isspace() -> bool\n\
-\n\
-Return True if all characters in S are whitespace\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-unicode_isspace(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1 &&
- Py_UNICODE_ISSPACE(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- for (; p < e; p++) {
- if (!Py_UNICODE_ISSPACE(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-PyDoc_STRVAR(isalpha__doc__,
-"S.isalpha() -> bool\n\
-\n\
-Return True if all characters in S are alphabetic\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-unicode_isalpha(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1 &&
- Py_UNICODE_ISALPHA(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- for (; p < e; p++) {
- if (!Py_UNICODE_ISALPHA(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-PyDoc_STRVAR(isalnum__doc__,
-"S.isalnum() -> bool\n\
-\n\
-Return True if all characters in S are alphanumeric\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-unicode_isalnum(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1 &&
- Py_UNICODE_ISALNUM(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- for (; p < e; p++) {
- if (!Py_UNICODE_ISALNUM(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-PyDoc_STRVAR(isdecimal__doc__,
-"S.isdecimal() -> bool\n\
-\n\
-Return True if there are only decimal characters in S,\n\
-False otherwise.");
-
-static PyObject*
-unicode_isdecimal(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1 &&
- Py_UNICODE_ISDECIMAL(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- for (; p < e; p++) {
- if (!Py_UNICODE_ISDECIMAL(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-PyDoc_STRVAR(isdigit__doc__,
-"S.isdigit() -> bool\n\
-\n\
-Return True if all characters in S are digits\n\
-and there is at least one character in S, False otherwise.");
-
-static PyObject*
-unicode_isdigit(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1 &&
- Py_UNICODE_ISDIGIT(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- for (; p < e; p++) {
- if (!Py_UNICODE_ISDIGIT(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-PyDoc_STRVAR(isnumeric__doc__,
-"S.isnumeric() -> bool\n\
-\n\
-Return True if there are only numeric characters in S,\n\
-False otherwise.");
-
-static PyObject*
-unicode_isnumeric(PyUnicodeObject *self)
-{
- register const Py_UNICODE *p = PyUnicode_AS_UNICODE(self);
- register const Py_UNICODE *e;
-
- /* Shortcut for single character strings */
- if (PyUnicode_GET_SIZE(self) == 1 &&
- Py_UNICODE_ISNUMERIC(*p))
- return PyBool_FromLong(1);
-
- /* Special case for empty strings */
- if (PyUnicode_GET_SIZE(self) == 0)
- return PyBool_FromLong(0);
-
- e = p + PyUnicode_GET_SIZE(self);
- for (; p < e; p++) {
- if (!Py_UNICODE_ISNUMERIC(*p))
- return PyBool_FromLong(0);
- }
- return PyBool_FromLong(1);
-}
-
-PyDoc_STRVAR(join__doc__,
-"S.join(sequence) -> unicode\n\
-\n\
-Return a string which is the concatenation of the strings in the\n\
-sequence. The separator between elements is S.");
-
-static PyObject*
-unicode_join(PyObject *self, PyObject *data)
-{
- return PyUnicode_Join(self, data);
-}
-
-static Py_ssize_t
-unicode_length(PyUnicodeObject *self)
-{
- return self->length;
-}
-
-PyDoc_STRVAR(ljust__doc__,
-"S.ljust(width[, fillchar]) -> int\n\
-\n\
-Return S left justified in a Unicode string of length width. Padding is\n\
-done using the specified fill character (default is a space).");
-
-static PyObject *
-unicode_ljust(PyUnicodeObject *self, PyObject *args)
-{
- Py_ssize_t width;
- Py_UNICODE fillchar = ' ';
-
- if (!PyArg_ParseTuple(args, "n|O&:ljust", &width, convert_uc, &fillchar))
- return NULL;
-
- if (self->length >= width && PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
-
- return (PyObject*) pad(self, 0, width - self->length, fillchar);
-}
-
-PyDoc_STRVAR(lower__doc__,
-"S.lower() -> unicode\n\
-\n\
-Return a copy of the string S converted to lowercase.");
-
-static PyObject*
-unicode_lower(PyUnicodeObject *self)
-{
- return fixup(self, fixlower);
-}
-
-#define LEFTSTRIP 0
-#define RIGHTSTRIP 1
-#define BOTHSTRIP 2
-
-/* Arrays indexed by above */
-static const char *stripformat[] = {"|O:lstrip", "|O:rstrip", "|O:strip"};
-
-#define STRIPNAME(i) (stripformat[i]+3)
-
-/* externally visible for str.strip(unicode) */
-PyObject *
-_PyUnicode_XStrip(PyUnicodeObject *self, int striptype, PyObject *sepobj)
-{
- Py_UNICODE *s = PyUnicode_AS_UNICODE(self);
- Py_ssize_t len = PyUnicode_GET_SIZE(self);
- Py_UNICODE *sep = PyUnicode_AS_UNICODE(sepobj);
- Py_ssize_t seplen = PyUnicode_GET_SIZE(sepobj);
- Py_ssize_t i, j;
-
- BLOOM_MASK sepmask = make_bloom_mask(sep, seplen);
-
- i = 0;
- if (striptype != RIGHTSTRIP) {
- while (i < len && BLOOM_MEMBER(sepmask, s[i], sep, seplen)) {
- i++;
- }
- }
-
- j = len;
- if (striptype != LEFTSTRIP) {
- do {
- j--;
- } while (j >= i && BLOOM_MEMBER(sepmask, s[j], sep, seplen));
- j++;
- }
-
- if (i == 0 && j == len && PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*)self;
- }
- else
- return PyUnicode_FromUnicode(s+i, j-i);
-}
-
-
-static PyObject *
-do_strip(PyUnicodeObject *self, int striptype)
-{
- Py_UNICODE *s = PyUnicode_AS_UNICODE(self);
- Py_ssize_t len = PyUnicode_GET_SIZE(self), i, j;
-
- i = 0;
- if (striptype != RIGHTSTRIP) {
- while (i < len && Py_UNICODE_ISSPACE(s[i])) {
- i++;
- }
- }
-
- j = len;
- if (striptype != LEFTSTRIP) {
- do {
- j--;
- } while (j >= i && Py_UNICODE_ISSPACE(s[j]));
- j++;
- }
-
- if (i == 0 && j == len && PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*)self;
- }
- else
- return PyUnicode_FromUnicode(s+i, j-i);
-}
-
-
-static PyObject *
-do_argstrip(PyUnicodeObject *self, int striptype, PyObject *args)
-{
- PyObject *sep = NULL;
-
- if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep))
- return NULL;
-
- if (sep != NULL && sep != Py_None) {
- if (PyUnicode_Check(sep))
- return _PyUnicode_XStrip(self, striptype, sep);
- else if (PyString_Check(sep)) {
- PyObject *res;
- sep = PyUnicode_FromObject(sep);
- if (sep==NULL)
- return NULL;
- res = _PyUnicode_XStrip(self, striptype, sep);
- Py_DECREF(sep);
- return res;
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "%s arg must be None, unicode or str",
- STRIPNAME(striptype));
- return NULL;
- }
- }
-
- return do_strip(self, striptype);
-}
-
-
-PyDoc_STRVAR(strip__doc__,
-"S.strip([chars]) -> unicode\n\
-\n\
-Return a copy of the string S with leading and trailing\n\
-whitespace removed.\n\
-If chars is given and not None, remove characters in chars instead.\n\
-If chars is a str, it will be converted to unicode before stripping");
-
-static PyObject *
-unicode_strip(PyUnicodeObject *self, PyObject *args)
-{
- if (PyTuple_GET_SIZE(args) == 0)
- return do_strip(self, BOTHSTRIP); /* Common case */
- else
- return do_argstrip(self, BOTHSTRIP, args);
-}
-
-
-PyDoc_STRVAR(lstrip__doc__,
-"S.lstrip([chars]) -> unicode\n\
-\n\
-Return a copy of the string S with leading whitespace removed.\n\
-If chars is given and not None, remove characters in chars instead.\n\
-If chars is a str, it will be converted to unicode before stripping");
-
-static PyObject *
-unicode_lstrip(PyUnicodeObject *self, PyObject *args)
-{
- if (PyTuple_GET_SIZE(args) == 0)
- return do_strip(self, LEFTSTRIP); /* Common case */
- else
- return do_argstrip(self, LEFTSTRIP, args);
-}
-
-
-PyDoc_STRVAR(rstrip__doc__,
-"S.rstrip([chars]) -> unicode\n\
-\n\
-Return a copy of the string S with trailing whitespace removed.\n\
-If chars is given and not None, remove characters in chars instead.\n\
-If chars is a str, it will be converted to unicode before stripping");
-
-static PyObject *
-unicode_rstrip(PyUnicodeObject *self, PyObject *args)
-{
- if (PyTuple_GET_SIZE(args) == 0)
- return do_strip(self, RIGHTSTRIP); /* Common case */
- else
- return do_argstrip(self, RIGHTSTRIP, args);
-}
-
-
-static PyObject*
-unicode_repeat(PyUnicodeObject *str, Py_ssize_t len)
-{
- PyUnicodeObject *u;
- Py_UNICODE *p;
- Py_ssize_t nchars;
- size_t nbytes;
-
- if (len < 0)
- len = 0;
-
- if (len == 1 && PyUnicode_CheckExact(str)) {
- /* no repeat, return original string */
- Py_INCREF(str);
- return (PyObject*) str;
- }
-
- /* ensure # of chars needed doesn't overflow int and # of bytes
- * needed doesn't overflow size_t
- */
- nchars = len * str->length;
- if (len && nchars / len != str->length) {
- PyErr_SetString(PyExc_OverflowError,
- "repeated string is too long");
- return NULL;
- }
- nbytes = (nchars + 1) * sizeof(Py_UNICODE);
- if (nbytes / sizeof(Py_UNICODE) != (size_t)(nchars + 1)) {
- PyErr_SetString(PyExc_OverflowError,
- "repeated string is too long");
- return NULL;
- }
- u = _PyUnicode_New(nchars);
- if (!u)
- return NULL;
-
- p = u->str;
-
- if (str->length == 1 && len > 0) {
- Py_UNICODE_FILL(p, str->str[0], len);
- } else {
- Py_ssize_t done = 0; /* number of characters copied this far */
- if (done < nchars) {
- Py_UNICODE_COPY(p, str->str, str->length);
- done = str->length;
- }
- while (done < nchars) {
- int n = (done <= nchars-done) ? done : nchars-done;
- Py_UNICODE_COPY(p+done, p, n);
- done += n;
- }
- }
-
- return (PyObject*) u;
-}
-
-PyObject *PyUnicode_Replace(PyObject *obj,
- PyObject *subobj,
- PyObject *replobj,
- Py_ssize_t maxcount)
-{
- PyObject *self;
- PyObject *str1;
- PyObject *str2;
- PyObject *result;
-
- self = PyUnicode_FromObject(obj);
- if (self == NULL)
- return NULL;
- str1 = PyUnicode_FromObject(subobj);
- if (str1 == NULL) {
- Py_DECREF(self);
- return NULL;
- }
- str2 = PyUnicode_FromObject(replobj);
- if (str2 == NULL) {
- Py_DECREF(self);
- Py_DECREF(str1);
- return NULL;
- }
- result = replace((PyUnicodeObject *)self,
- (PyUnicodeObject *)str1,
- (PyUnicodeObject *)str2,
- maxcount);
- Py_DECREF(self);
- Py_DECREF(str1);
- Py_DECREF(str2);
- return result;
-}
-
-PyDoc_STRVAR(replace__doc__,
-"S.replace (old, new[, maxsplit]) -> unicode\n\
-\n\
-Return a copy of S with all occurrences of substring\n\
-old replaced by new. If the optional argument maxsplit is\n\
-given, only the first maxsplit occurrences are replaced.");
-
-static PyObject*
-unicode_replace(PyUnicodeObject *self, PyObject *args)
-{
- PyUnicodeObject *str1;
- PyUnicodeObject *str2;
- Py_ssize_t maxcount = -1;
- PyObject *result;
-
- if (!PyArg_ParseTuple(args, "OO|n:replace", &str1, &str2, &maxcount))
- return NULL;
- str1 = (PyUnicodeObject *)PyUnicode_FromObject((PyObject *)str1);
- if (str1 == NULL)
- return NULL;
- str2 = (PyUnicodeObject *)PyUnicode_FromObject((PyObject *)str2);
- if (str2 == NULL) {
- Py_DECREF(str1);
- return NULL;
- }
-
- result = replace(self, str1, str2, maxcount);
-
- Py_DECREF(str1);
- Py_DECREF(str2);
- return result;
-}
-
-static
-PyObject *unicode_repr(PyObject *unicode)
-{
- return unicodeescape_string(PyUnicode_AS_UNICODE(unicode),
- PyUnicode_GET_SIZE(unicode),
- 1);
-}
-
-PyDoc_STRVAR(rfind__doc__,
-"S.rfind(sub [,start [,end]]) -> int\n\
-\n\
-Return the highest index in S where substring sub is found,\n\
-such that sub is contained within s[start,end]. Optional\n\
-arguments start and end are interpreted as in slice notation.\n\
-\n\
-Return -1 on failure.");
-
-static PyObject *
-unicode_rfind(PyUnicodeObject *self, PyObject *args)
-{
- PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- Py_ssize_t result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:rfind", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
-
- result = stringlib_rfind_slice(
- PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),
- PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),
- start, end
- );
-
- Py_DECREF(substring);
-
- return PyInt_FromSsize_t(result);
-}
-
-PyDoc_STRVAR(rindex__doc__,
-"S.rindex(sub [,start [,end]]) -> int\n\
-\n\
-Like S.rfind() but raise ValueError when the substring is not found.");
-
-static PyObject *
-unicode_rindex(PyUnicodeObject *self, PyObject *args)
-{
- PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- Py_ssize_t result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:rindex", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
-
- result = stringlib_rfind_slice(
- PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),
- PyUnicode_AS_UNICODE(substring), PyUnicode_GET_SIZE(substring),
- start, end
- );
-
- Py_DECREF(substring);
-
- if (result < 0) {
- PyErr_SetString(PyExc_ValueError, "substring not found");
- return NULL;
- }
- return PyInt_FromSsize_t(result);
-}
-
-PyDoc_STRVAR(rjust__doc__,
-"S.rjust(width[, fillchar]) -> unicode\n\
-\n\
-Return S right justified in a Unicode string of length width. Padding is\n\
-done using the specified fill character (default is a space).");
-
-static PyObject *
-unicode_rjust(PyUnicodeObject *self, PyObject *args)
-{
- Py_ssize_t width;
- Py_UNICODE fillchar = ' ';
-
- if (!PyArg_ParseTuple(args, "n|O&:rjust", &width, convert_uc, &fillchar))
- return NULL;
-
- if (self->length >= width && PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
-
- return (PyObject*) pad(self, width - self->length, 0, fillchar);
-}
-
-static PyObject*
-unicode_slice(PyUnicodeObject *self, Py_ssize_t start, Py_ssize_t end)
-{
- /* standard clamping */
- if (start < 0)
- start = 0;
- if (end < 0)
- end = 0;
- if (end > self->length)
- end = self->length;
- if (start == 0 && end == self->length && PyUnicode_CheckExact(self)) {
- /* full slice, return original string */
- Py_INCREF(self);
- return (PyObject*) self;
- }
- if (start > end)
- start = end;
- /* copy slice */
- return (PyObject*) PyUnicode_FromUnicode(self->str + start,
- end - start);
-}
-
-PyObject *PyUnicode_Split(PyObject *s,
- PyObject *sep,
- Py_ssize_t maxsplit)
-{
- PyObject *result;
-
- s = PyUnicode_FromObject(s);
- if (s == NULL)
- return NULL;
- if (sep != NULL) {
- sep = PyUnicode_FromObject(sep);
- if (sep == NULL) {
- Py_DECREF(s);
- return NULL;
- }
- }
-
- result = split((PyUnicodeObject *)s, (PyUnicodeObject *)sep, maxsplit);
-
- Py_DECREF(s);
- Py_XDECREF(sep);
- return result;
-}
-
-PyDoc_STRVAR(split__doc__,
-"S.split([sep [,maxsplit]]) -> list of strings\n\
-\n\
-Return a list of the words in S, using sep as the\n\
-delimiter string. If maxsplit is given, at most maxsplit\n\
-splits are done. If sep is not specified or is None,\n\
-any whitespace string is a separator.");
-
-static PyObject*
-unicode_split(PyUnicodeObject *self, PyObject *args)
-{
- PyObject *substring = Py_None;
- Py_ssize_t maxcount = -1;
-
- if (!PyArg_ParseTuple(args, "|On:split", &substring, &maxcount))
- return NULL;
-
- if (substring == Py_None)
- return split(self, NULL, maxcount);
- else if (PyUnicode_Check(substring))
- return split(self, (PyUnicodeObject *)substring, maxcount);
- else
- return PyUnicode_Split((PyObject *)self, substring, maxcount);
-}
-
-PyObject *
-PyUnicode_Partition(PyObject *str_in, PyObject *sep_in)
-{
- PyObject* str_obj;
- PyObject* sep_obj;
- PyObject* out;
-
- str_obj = PyUnicode_FromObject(str_in);
- if (!str_obj)
- return NULL;
- sep_obj = PyUnicode_FromObject(sep_in);
- if (!sep_obj) {
- Py_DECREF(str_obj);
- return NULL;
- }
-
- out = stringlib_partition(
- str_obj, PyUnicode_AS_UNICODE(str_obj), PyUnicode_GET_SIZE(str_obj),
- sep_obj, PyUnicode_AS_UNICODE(sep_obj), PyUnicode_GET_SIZE(sep_obj)
- );
-
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
-
- return out;
-}
-
-
-PyObject *
-PyUnicode_RPartition(PyObject *str_in, PyObject *sep_in)
-{
- PyObject* str_obj;
- PyObject* sep_obj;
- PyObject* out;
-
- str_obj = PyUnicode_FromObject(str_in);
- if (!str_obj)
- return NULL;
- sep_obj = PyUnicode_FromObject(sep_in);
- if (!sep_obj) {
- Py_DECREF(str_obj);
- return NULL;
- }
-
- out = stringlib_rpartition(
- str_obj, PyUnicode_AS_UNICODE(str_obj), PyUnicode_GET_SIZE(str_obj),
- sep_obj, PyUnicode_AS_UNICODE(sep_obj), PyUnicode_GET_SIZE(sep_obj)
- );
-
- Py_DECREF(sep_obj);
- Py_DECREF(str_obj);
-
- return out;
-}
-
-PyDoc_STRVAR(partition__doc__,
-"S.partition(sep) -> (head, sep, tail)\n\
-\n\
-Searches for the separator sep in S, and returns the part before it,\n\
-the separator itself, and the part after it. If the separator is not\n\
-found, returns S and two empty strings.");
-
-static PyObject*
-unicode_partition(PyUnicodeObject *self, PyObject *separator)
-{
- return PyUnicode_Partition((PyObject *)self, separator);
-}
-
-PyDoc_STRVAR(rpartition__doc__,
-"S.rpartition(sep) -> (tail, sep, head)\n\
-\n\
-Searches for the separator sep in S, starting at the end of S, and returns\n\
-the part before it, the separator itself, and the part after it. If the\n\
-separator is not found, returns two empty strings and S.");
-
-static PyObject*
-unicode_rpartition(PyUnicodeObject *self, PyObject *separator)
-{
- return PyUnicode_RPartition((PyObject *)self, separator);
-}
-
-PyObject *PyUnicode_RSplit(PyObject *s,
- PyObject *sep,
- Py_ssize_t maxsplit)
-{
- PyObject *result;
-
- s = PyUnicode_FromObject(s);
- if (s == NULL)
- return NULL;
- if (sep != NULL) {
- sep = PyUnicode_FromObject(sep);
- if (sep == NULL) {
- Py_DECREF(s);
- return NULL;
- }
- }
-
- result = rsplit((PyUnicodeObject *)s, (PyUnicodeObject *)sep, maxsplit);
-
- Py_DECREF(s);
- Py_XDECREF(sep);
- return result;
-}
-
-PyDoc_STRVAR(rsplit__doc__,
-"S.rsplit([sep [,maxsplit]]) -> list of strings\n\
-\n\
-Return a list of the words in S, using sep as the\n\
-delimiter string, starting at the end of the string and\n\
-working to the front. If maxsplit is given, at most maxsplit\n\
-splits are done. If sep is not specified, any whitespace string\n\
-is a separator.");
-
-static PyObject*
-unicode_rsplit(PyUnicodeObject *self, PyObject *args)
-{
- PyObject *substring = Py_None;
- Py_ssize_t maxcount = -1;
-
- if (!PyArg_ParseTuple(args, "|On:rsplit", &substring, &maxcount))
- return NULL;
-
- if (substring == Py_None)
- return rsplit(self, NULL, maxcount);
- else if (PyUnicode_Check(substring))
- return rsplit(self, (PyUnicodeObject *)substring, maxcount);
- else
- return PyUnicode_RSplit((PyObject *)self, substring, maxcount);
-}
-
-PyDoc_STRVAR(splitlines__doc__,
-"S.splitlines([keepends]]) -> list of strings\n\
-\n\
-Return a list of the lines in S, breaking at line boundaries.\n\
-Line breaks are not included in the resulting list unless keepends\n\
-is given and true.");
-
-static PyObject*
-unicode_splitlines(PyUnicodeObject *self, PyObject *args)
-{
- int keepends = 0;
-
- if (!PyArg_ParseTuple(args, "|i:splitlines", &keepends))
- return NULL;
-
- return PyUnicode_Splitlines((PyObject *)self, keepends);
-}
-
-static
-PyObject *unicode_str(PyUnicodeObject *self)
-{
- return PyUnicode_AsEncodedString((PyObject *)self, NULL, NULL);
-}
-
-PyDoc_STRVAR(swapcase__doc__,
-"S.swapcase() -> unicode\n\
-\n\
-Return a copy of S with uppercase characters converted to lowercase\n\
-and vice versa.");
-
-static PyObject*
-unicode_swapcase(PyUnicodeObject *self)
-{
- return fixup(self, fixswapcase);
-}
-
-PyDoc_STRVAR(translate__doc__,
-"S.translate(table) -> unicode\n\
-\n\
-Return a copy of the string S, where all characters have been mapped\n\
-through the given translation table, which must be a mapping of\n\
-Unicode ordinals to Unicode ordinals, Unicode strings or None.\n\
-Unmapped characters are left untouched. Characters mapped to None\n\
-are deleted.");
-
-static PyObject*
-unicode_translate(PyUnicodeObject *self, PyObject *table)
-{
- return PyUnicode_TranslateCharmap(self->str,
- self->length,
- table,
- "ignore");
-}
-
-PyDoc_STRVAR(upper__doc__,
-"S.upper() -> unicode\n\
-\n\
-Return a copy of S converted to uppercase.");
-
-static PyObject*
-unicode_upper(PyUnicodeObject *self)
-{
- return fixup(self, fixupper);
-}
-
-PyDoc_STRVAR(zfill__doc__,
-"S.zfill(width) -> unicode\n\
-\n\
-Pad a numeric string x with zeros on the left, to fill a field\n\
-of the specified width. The string x is never truncated.");
-
-static PyObject *
-unicode_zfill(PyUnicodeObject *self, PyObject *args)
-{
- Py_ssize_t fill;
- PyUnicodeObject *u;
-
- Py_ssize_t width;
- if (!PyArg_ParseTuple(args, "n:zfill", &width))
- return NULL;
-
- if (self->length >= width) {
- if (PyUnicode_CheckExact(self)) {
- Py_INCREF(self);
- return (PyObject*) self;
- }
- else
- return PyUnicode_FromUnicode(
- PyUnicode_AS_UNICODE(self),
- PyUnicode_GET_SIZE(self)
- );
- }
-
- fill = width - self->length;
-
- u = pad(self, fill, 0, '0');
-
- if (u == NULL)
- return NULL;
-
- if (u->str[fill] == '+' || u->str[fill] == '-') {
- /* move sign to beginning of string */
- u->str[0] = u->str[fill];
- u->str[fill] = '0';
- }
-
- return (PyObject*) u;
-}
-
-#if 0
-static PyObject*
-unicode_freelistsize(PyUnicodeObject *self)
-{
- return PyInt_FromLong(unicode_freelist_size);
-}
-#endif
-
-PyDoc_STRVAR(startswith__doc__,
-"S.startswith(prefix[, start[, end]]) -> bool\n\
-\n\
-Return True if S starts with the specified prefix, False otherwise.\n\
-With optional start, test S beginning at that position.\n\
-With optional end, stop comparing S at that position.\n\
-prefix can also be a tuple of strings to try.");
-
-static PyObject *
-unicode_startswith(PyUnicodeObject *self,
- PyObject *args)
-{
- PyObject *subobj;
- PyUnicodeObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- int result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:startswith", &subobj,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- substring = (PyUnicodeObject *)PyUnicode_FromObject(
- PyTuple_GET_ITEM(subobj, i));
- if (substring == NULL)
- return NULL;
- result = tailmatch(self, substring, start, end, -1);
- Py_DECREF(substring);
- if (result) {
- Py_RETURN_TRUE;
- }
- }
- /* nothing matched */
- Py_RETURN_FALSE;
- }
- substring = (PyUnicodeObject *)PyUnicode_FromObject(subobj);
- if (substring == NULL)
- return NULL;
- result = tailmatch(self, substring, start, end, -1);
- Py_DECREF(substring);
- return PyBool_FromLong(result);
-}
-
-
-PyDoc_STRVAR(endswith__doc__,
-"S.endswith(suffix[, start[, end]]) -> bool\n\
-\n\
-Return True if S ends with the specified suffix, False otherwise.\n\
-With optional start, test S beginning at that position.\n\
-With optional end, stop comparing S at that position.\n\
-suffix can also be a tuple of strings to try.");
-
-static PyObject *
-unicode_endswith(PyUnicodeObject *self,
- PyObject *args)
-{
- PyObject *subobj;
- PyUnicodeObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
- int result;
-
- if (!PyArg_ParseTuple(args, "O|O&O&:endswith", &subobj,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- if (PyTuple_Check(subobj)) {
- Py_ssize_t i;
- for (i = 0; i < PyTuple_GET_SIZE(subobj); i++) {
- substring = (PyUnicodeObject *)PyUnicode_FromObject(
- PyTuple_GET_ITEM(subobj, i));
- if (substring == NULL)
- return NULL;
- result = tailmatch(self, substring, start, end, +1);
- Py_DECREF(substring);
- if (result) {
- Py_RETURN_TRUE;
- }
- }
- Py_RETURN_FALSE;
- }
- substring = (PyUnicodeObject *)PyUnicode_FromObject(subobj);
- if (substring == NULL)
- return NULL;
-
- result = tailmatch(self, substring, start, end, +1);
- Py_DECREF(substring);
- return PyBool_FromLong(result);
-}
-
-
-
-static PyObject *
-unicode_getnewargs(PyUnicodeObject *v)
-{
- return Py_BuildValue("(u#)", v->str, v->length);
-}
-
-
-static PyMethodDef unicode_methods[] = {
-
- /* Order is according to common usage: often used methods should
- appear first, since lookup is done sequentially. */
-
- {"encode", (PyCFunction) unicode_encode, METH_VARARGS, encode__doc__},
- {"replace", (PyCFunction) unicode_replace, METH_VARARGS, replace__doc__},
- {"split", (PyCFunction) unicode_split, METH_VARARGS, split__doc__},
- {"rsplit", (PyCFunction) unicode_rsplit, METH_VARARGS, rsplit__doc__},
- {"join", (PyCFunction) unicode_join, METH_O, join__doc__},
- {"capitalize", (PyCFunction) unicode_capitalize, METH_NOARGS, capitalize__doc__},
- {"title", (PyCFunction) unicode_title, METH_NOARGS, title__doc__},
- {"center", (PyCFunction) unicode_center, METH_VARARGS, center__doc__},
- {"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__},
- {"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__},
- {"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__},
- {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__},
- {"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__},
- {"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__},
- {"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__},
- {"lstrip", (PyCFunction) unicode_lstrip, METH_VARARGS, lstrip__doc__},
- {"decode", (PyCFunction) unicode_decode, METH_VARARGS, decode__doc__},
-/* {"maketrans", (PyCFunction) unicode_maketrans, METH_VARARGS, maketrans__doc__}, */
- {"rfind", (PyCFunction) unicode_rfind, METH_VARARGS, rfind__doc__},
- {"rindex", (PyCFunction) unicode_rindex, METH_VARARGS, rindex__doc__},
- {"rjust", (PyCFunction) unicode_rjust, METH_VARARGS, rjust__doc__},
- {"rstrip", (PyCFunction) unicode_rstrip, METH_VARARGS, rstrip__doc__},
- {"rpartition", (PyCFunction) unicode_rpartition, METH_O, rpartition__doc__},
- {"splitlines", (PyCFunction) unicode_splitlines, METH_VARARGS, splitlines__doc__},
- {"strip", (PyCFunction) unicode_strip, METH_VARARGS, strip__doc__},
- {"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__},
- {"translate", (PyCFunction) unicode_translate, METH_O, translate__doc__},
- {"upper", (PyCFunction) unicode_upper, METH_NOARGS, upper__doc__},
- {"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__},
- {"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__},
- {"islower", (PyCFunction) unicode_islower, METH_NOARGS, islower__doc__},
- {"isupper", (PyCFunction) unicode_isupper, METH_NOARGS, isupper__doc__},
- {"istitle", (PyCFunction) unicode_istitle, METH_NOARGS, istitle__doc__},
- {"isspace", (PyCFunction) unicode_isspace, METH_NOARGS, isspace__doc__},
- {"isdecimal", (PyCFunction) unicode_isdecimal, METH_NOARGS, isdecimal__doc__},
- {"isdigit", (PyCFunction) unicode_isdigit, METH_NOARGS, isdigit__doc__},
- {"isnumeric", (PyCFunction) unicode_isnumeric, METH_NOARGS, isnumeric__doc__},
- {"isalpha", (PyCFunction) unicode_isalpha, METH_NOARGS, isalpha__doc__},
- {"isalnum", (PyCFunction) unicode_isalnum, METH_NOARGS, isalnum__doc__},
- {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__},
-#if 0
- {"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__},
-#endif
-
-#if 0
- /* This one is just used for debugging the implementation. */
- {"freelistsize", (PyCFunction) unicode_freelistsize, METH_NOARGS},
-#endif
-
- {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS},
- {NULL, NULL}
-};
-
-static PyObject *
-unicode_mod(PyObject *v, PyObject *w)
-{
- if (!PyUnicode_Check(v)) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- return PyUnicode_Format(v, w);
-}
-
-static PyNumberMethods unicode_as_number = {
- 0, /*nb_add*/
- 0, /*nb_subtract*/
- 0, /*nb_multiply*/
- 0, /*nb_divide*/
- unicode_mod, /*nb_remainder*/
-};
-
-static PySequenceMethods unicode_as_sequence = {
- (lenfunc) unicode_length, /* sq_length */
- PyUnicode_Concat, /* sq_concat */
- (ssizeargfunc) unicode_repeat, /* sq_repeat */
- (ssizeargfunc) unicode_getitem, /* sq_item */
- (ssizessizeargfunc) unicode_slice, /* sq_slice */
- 0, /* sq_ass_item */
- 0, /* sq_ass_slice */
- PyUnicode_Contains, /* sq_contains */
-};
-
-static PyObject*
-unicode_subscript(PyUnicodeObject* self, PyObject* item)
-{
- if (PyIndex_Check(item)) {
- Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
- if (i == -1 && PyErr_Occurred())
- return NULL;
- if (i < 0)
- i += PyUnicode_GET_SIZE(self);
- return unicode_getitem(self, i);
- } else if (PySlice_Check(item)) {
- Py_ssize_t start, stop, step, slicelength, cur, i;
- Py_UNICODE* source_buf;
- Py_UNICODE* result_buf;
- PyObject* result;
-
- if (PySlice_GetIndicesEx((PySliceObject*)item, PyUnicode_GET_SIZE(self),
- &start, &stop, &step, &slicelength) < 0) {
- return NULL;
- }
-
- if (slicelength <= 0) {
- return PyUnicode_FromUnicode(NULL, 0);
- } else {
- source_buf = PyUnicode_AS_UNICODE((PyObject*)self);
- result_buf = (Py_UNICODE *)PyMem_MALLOC(slicelength*
- sizeof(Py_UNICODE));
-
- if (result_buf == NULL)
- return PyErr_NoMemory();
-
- for (cur = start, i = 0; i < slicelength; cur += step, i++) {
- result_buf[i] = source_buf[cur];
- }
-
- result = PyUnicode_FromUnicode(result_buf, slicelength);
- PyMem_FREE(result_buf);
- return result;
- }
- } else {
- PyErr_SetString(PyExc_TypeError, "string indices must be integers");
- return NULL;
- }
-}
-
-static PyMappingMethods unicode_as_mapping = {
- (lenfunc)unicode_length, /* mp_length */
- (binaryfunc)unicode_subscript, /* mp_subscript */
- (objobjargproc)0, /* mp_ass_subscript */
-};
-
-static Py_ssize_t
-unicode_buffer_getreadbuf(PyUnicodeObject *self,
- Py_ssize_t index,
- const void **ptr)
-{
- if (index != 0) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent unicode segment");
- return -1;
- }
- *ptr = (void *) self->str;
- return PyUnicode_GET_DATA_SIZE(self);
-}
-
-static Py_ssize_t
-unicode_buffer_getwritebuf(PyUnicodeObject *self, Py_ssize_t index,
- const void **ptr)
-{
- PyErr_SetString(PyExc_TypeError,
- "cannot use unicode as modifiable buffer");
- return -1;
-}
-
-static int
-unicode_buffer_getsegcount(PyUnicodeObject *self,
- Py_ssize_t *lenp)
-{
- if (lenp)
- *lenp = PyUnicode_GET_DATA_SIZE(self);
- return 1;
-}
-
-static Py_ssize_t
-unicode_buffer_getcharbuf(PyUnicodeObject *self,
- Py_ssize_t index,
- const void **ptr)
-{
- PyObject *str;
-
- if (index != 0) {
- PyErr_SetString(PyExc_SystemError,
- "accessing non-existent unicode segment");
- return -1;
- }
- str = _PyUnicode_AsDefaultEncodedString((PyObject *)self, NULL);
- if (str == NULL)
- return -1;
- *ptr = (void *) PyString_AS_STRING(str);
- return PyString_GET_SIZE(str);
-}
-
-/* Helpers for PyUnicode_Format() */
-
-static PyObject *
-getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx)
-{
- Py_ssize_t argidx = *p_argidx;
- if (argidx < arglen) {
- (*p_argidx)++;
- if (arglen < 0)
- return args;
- else
- return PyTuple_GetItem(args, argidx);
- }
- PyErr_SetString(PyExc_TypeError,
- "not enough arguments for format string");
- return NULL;
-}
-
-#define F_LJUST (1<<0)
-#define F_SIGN (1<<1)
-#define F_BLANK (1<<2)
-#define F_ALT (1<<3)
-#define F_ZERO (1<<4)
-
-static Py_ssize_t
-strtounicode(Py_UNICODE *buffer, const char *charbuffer)
-{
- register Py_ssize_t i;
- Py_ssize_t len = strlen(charbuffer);
- for (i = len - 1; i >= 0; i--)
- buffer[i] = (Py_UNICODE) charbuffer[i];
-
- return len;
-}
-
-static int
-doubletounicode(Py_UNICODE *buffer, size_t len, const char *format, double x)
-{
- Py_ssize_t result;
-
- PyOS_ascii_formatd((char *)buffer, len, format, x);
- result = strtounicode(buffer, (char *)buffer);
- return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);
-}
-
-static int
-longtounicode(Py_UNICODE *buffer, size_t len, const char *format, long x)
-{
- Py_ssize_t result;
-
- PyOS_snprintf((char *)buffer, len, format, x);
- result = strtounicode(buffer, (char *)buffer);
- return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);
-}
-
-/* XXX To save some code duplication, formatfloat/long/int could have been
- shared with stringobject.c, converting from 8-bit to Unicode after the
- formatting is done. */
-
-static int
-formatfloat(Py_UNICODE *buf,
- size_t buflen,
- int flags,
- int prec,
- int type,
- PyObject *v)
-{
- /* fmt = '%#.' + `prec` + `type`
- worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/
- char fmt[20];
- double x;
-
- x = PyFloat_AsDouble(v);
- if (x == -1.0 && PyErr_Occurred())
- return -1;
- if (prec < 0)
- prec = 6;
- if (type == 'f' && (fabs(x) / 1e25) >= 1e25)
- type = 'g';
- /* Worst case length calc to ensure no buffer overrun:
-
- 'g' formats:
- fmt = %#.<prec>g
- buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp
- for any double rep.)
- len = 1 + prec + 1 + 2 + 5 = 9 + prec
-
- 'f' formats:
- buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50)
- len = 1 + 50 + 1 + prec = 52 + prec
-
- If prec=0 the effective precision is 1 (the leading digit is
- always given), therefore increase the length by one.
-
- */
- if ((type == 'g' && buflen <= (size_t)10 + (size_t)prec) ||
- (type == 'f' && buflen <= (size_t)53 + (size_t)prec)) {
- PyErr_SetString(PyExc_OverflowError,
- "formatted float is too long (precision too large?)");
- return -1;
- }
- PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c",
- (flags&F_ALT) ? "#" : "",
- prec, type);
- return doubletounicode(buf, buflen, fmt, x);
-}
-
-static PyObject*
-formatlong(PyObject *val, int flags, int prec, int type)
-{
- char *buf;
- int i, len;
- PyObject *str; /* temporary string object. */
- PyUnicodeObject *result;
-
- str = _PyString_FormatLong(val, flags, prec, type, &buf, &len);
- if (!str)
- return NULL;
- result = _PyUnicode_New(len);
- if (!result) {
- Py_DECREF(str);
- return NULL;
- }
- for (i = 0; i < len; i++)
- result->str[i] = buf[i];
- result->str[len] = 0;
- Py_DECREF(str);
- return (PyObject*)result;
-}
-
-static int
-formatint(Py_UNICODE *buf,
- size_t buflen,
- int flags,
- int prec,
- int type,
- PyObject *v)
-{
- /* fmt = '%#.' + `prec` + 'l' + `type`
- * worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine)
- * + 1 + 1
- * = 24
- */
- char fmt[64]; /* plenty big enough! */
- char *sign;
- long x;
-
- x = PyInt_AsLong(v);
- if (x == -1 && PyErr_Occurred())
- return -1;
- if (x < 0 && type == 'u') {
- type = 'd';
- }
- if (x < 0 && (type == 'x' || type == 'X' || type == 'o'))
- sign = "-";
- else
- sign = "";
- if (prec < 0)
- prec = 1;
-
- /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal))
- * worst case buf = '-0x' + [0-9]*prec, where prec >= 11
- */
- if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) {
- PyErr_SetString(PyExc_OverflowError,
- "formatted integer is too long (precision too large?)");
- return -1;
- }
-
- if ((flags & F_ALT) &&
- (type == 'x' || type == 'X')) {
- /* When converting under %#x or %#X, there are a number
- * of issues that cause pain:
- * - when 0 is being converted, the C standard leaves off
- * the '0x' or '0X', which is inconsistent with other
- * %#x/%#X conversions and inconsistent with Python's
- * hex() function
- * - there are platforms that violate the standard and
- * convert 0 with the '0x' or '0X'
- * (Metrowerks, Compaq Tru64)
- * - there are platforms that give '0x' when converting
- * under %#X, but convert 0 in accordance with the
- * standard (OS/2 EMX)
- *
- * We can achieve the desired consistency by inserting our
- * own '0x' or '0X' prefix, and substituting %x/%X in place
- * of %#x/%#X.
- *
- * Note that this is the same approach as used in
- * formatint() in stringobject.c
- */
- PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c",
- sign, type, prec, type);
- }
- else {
- PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c",
- sign, (flags&F_ALT) ? "#" : "",
- prec, type);
- }
- if (sign[0])
- return longtounicode(buf, buflen, fmt, -x);
- else
- return longtounicode(buf, buflen, fmt, x);
-}
-
-static int
-formatchar(Py_UNICODE *buf,
- size_t buflen,
- PyObject *v)
-{
- /* presume that the buffer is at least 2 characters long */
- if (PyUnicode_Check(v)) {
- if (PyUnicode_GET_SIZE(v) != 1)
- goto onError;
- buf[0] = PyUnicode_AS_UNICODE(v)[0];
- }
-
- else if (PyString_Check(v)) {
- if (PyString_GET_SIZE(v) != 1)
- goto onError;
- buf[0] = (Py_UNICODE)PyString_AS_STRING(v)[0];
- }
-
- else {
- /* Integer input truncated to a character */
- long x;
- x = PyInt_AsLong(v);
- if (x == -1 && PyErr_Occurred())
- goto onError;
-#ifdef Py_UNICODE_WIDE
- if (x < 0 || x > 0x10ffff) {
- PyErr_SetString(PyExc_OverflowError,
- "%c arg not in range(0x110000) "
- "(wide Python build)");
- return -1;
- }
-#else
- if (x < 0 || x > 0xffff) {
- PyErr_SetString(PyExc_OverflowError,
- "%c arg not in range(0x10000) "
- "(narrow Python build)");
- return -1;
- }
-#endif
- buf[0] = (Py_UNICODE) x;
- }
- buf[1] = '\0';
- return 1;
-
- onError:
- PyErr_SetString(PyExc_TypeError,
- "%c requires int or char");
- return -1;
-}
-
-/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)
-
- FORMATBUFLEN is the length of the buffer in which the floats, ints, &
- chars are formatted. XXX This is a magic number. Each formatting
- routine does bounds checking to ensure no overflow, but a better
- solution may be to malloc a buffer of appropriate size for each
- format. For now, the current solution is sufficient.
-*/
-#define FORMATBUFLEN (size_t)120
-
-PyObject *PyUnicode_Format(PyObject *format,
- PyObject *args)
-{
- Py_UNICODE *fmt, *res;
- Py_ssize_t fmtcnt, rescnt, reslen, arglen, argidx;
- int args_owned = 0;
- PyUnicodeObject *result = NULL;
- PyObject *dict = NULL;
- PyObject *uformat;
-
- if (format == NULL || args == NULL) {
- PyErr_BadInternalCall();
- return NULL;
- }
- uformat = PyUnicode_FromObject(format);
- if (uformat == NULL)
- return NULL;
- fmt = PyUnicode_AS_UNICODE(uformat);
- fmtcnt = PyUnicode_GET_SIZE(uformat);
-
- reslen = rescnt = fmtcnt + 100;
- result = _PyUnicode_New(reslen);
- if (result == NULL)
- goto onError;
- res = PyUnicode_AS_UNICODE(result);
-
- if (PyTuple_Check(args)) {
- arglen = PyTuple_Size(args);
- argidx = 0;
- }
- else {
- arglen = -1;
- argidx = -2;
- }
- if (args->ob_type->tp_as_mapping && !PyTuple_Check(args) &&
- !PyObject_TypeCheck(args, &PyBaseString_Type))
- dict = args;
-
- while (--fmtcnt >= 0) {
- if (*fmt != '%') {
- if (--rescnt < 0) {
- rescnt = fmtcnt + 100;
- reslen += rescnt;
- if (_PyUnicode_Resize(&result, reslen) < 0)
- goto onError;
- res = PyUnicode_AS_UNICODE(result) + reslen - rescnt;
- --rescnt;
- }
- *res++ = *fmt++;
- }
- else {
- /* Got a format specifier */
- int flags = 0;
- Py_ssize_t width = -1;
- int prec = -1;
- Py_UNICODE c = '\0';
- Py_UNICODE fill;
- PyObject *v = NULL;
- PyObject *temp = NULL;
- Py_UNICODE *pbuf;
- Py_UNICODE sign;
- Py_ssize_t len;
- Py_UNICODE formatbuf[FORMATBUFLEN]; /* For format{float,int,char}() */
-
- fmt++;
- if (*fmt == '(') {
- Py_UNICODE *keystart;
- Py_ssize_t keylen;
- PyObject *key;
- int pcount = 1;
-
- if (dict == NULL) {
- PyErr_SetString(PyExc_TypeError,
- "format requires a mapping");
- goto onError;
- }
- ++fmt;
- --fmtcnt;
- keystart = fmt;
- /* Skip over balanced parentheses */
- while (pcount > 0 && --fmtcnt >= 0) {
- if (*fmt == ')')
- --pcount;
- else if (*fmt == '(')
- ++pcount;
- fmt++;
- }
- keylen = fmt - keystart - 1;
- if (fmtcnt < 0 || pcount > 0) {
- PyErr_SetString(PyExc_ValueError,
- "incomplete format key");
- goto onError;
- }
-#if 0
- /* keys are converted to strings using UTF-8 and
- then looked up since Python uses strings to hold
- variables names etc. in its namespaces and we
- wouldn't want to break common idioms. */
- key = PyUnicode_EncodeUTF8(keystart,
- keylen,
- NULL);
-#else
- key = PyUnicode_FromUnicode(keystart, keylen);
-#endif
- if (key == NULL)
- goto onError;
- if (args_owned) {
- Py_DECREF(args);
- args_owned = 0;
- }
- args = PyObject_GetItem(dict, key);
- Py_DECREF(key);
- if (args == NULL) {
- goto onError;
- }
- args_owned = 1;
- arglen = -1;
- argidx = -2;
- }
- while (--fmtcnt >= 0) {
- switch (c = *fmt++) {
- case '-': flags |= F_LJUST; continue;
- case '+': flags |= F_SIGN; continue;
- case ' ': flags |= F_BLANK; continue;
- case '#': flags |= F_ALT; continue;
- case '0': flags |= F_ZERO; continue;
- }
- break;
- }
- if (c == '*') {
- v = getnextarg(args, arglen, &argidx);
- if (v == NULL)
- goto onError;
- if (!PyInt_Check(v)) {
- PyErr_SetString(PyExc_TypeError,
- "* wants int");
- goto onError;
- }
- width = PyInt_AsLong(v);
- if (width < 0) {
- flags |= F_LJUST;
- width = -width;
- }
- if (--fmtcnt >= 0)
- c = *fmt++;
- }
- else if (c >= '0' && c <= '9') {
- width = c - '0';
- while (--fmtcnt >= 0) {
- c = *fmt++;
- if (c < '0' || c > '9')
- break;
- if ((width*10) / 10 != width) {
- PyErr_SetString(PyExc_ValueError,
- "width too big");
- goto onError;
- }
- width = width*10 + (c - '0');
- }
- }
- if (c == '.') {
- prec = 0;
- if (--fmtcnt >= 0)
- c = *fmt++;
- if (c == '*') {
- v = getnextarg(args, arglen, &argidx);
- if (v == NULL)
- goto onError;
- if (!PyInt_Check(v)) {
- PyErr_SetString(PyExc_TypeError,
- "* wants int");
- goto onError;
- }
- prec = PyInt_AsLong(v);
- if (prec < 0)
- prec = 0;
- if (--fmtcnt >= 0)
- c = *fmt++;
- }
- else if (c >= '0' && c <= '9') {
- prec = c - '0';
- while (--fmtcnt >= 0) {
- c = Py_CHARMASK(*fmt++);
- if (c < '0' || c > '9')
- break;
- if ((prec*10) / 10 != prec) {
- PyErr_SetString(PyExc_ValueError,
- "prec too big");
- goto onError;
- }
- prec = prec*10 + (c - '0');
- }
- }
- } /* prec */
- if (fmtcnt >= 0) {
- if (c == 'h' || c == 'l' || c == 'L') {
- if (--fmtcnt >= 0)
- c = *fmt++;
- }
- }
- if (fmtcnt < 0) {
- PyErr_SetString(PyExc_ValueError,
- "incomplete format");
- goto onError;
- }
- if (c != '%') {
- v = getnextarg(args, arglen, &argidx);
- if (v == NULL)
- goto onError;
- }
- sign = 0;
- fill = ' ';
- switch (c) {
-
- case '%':
- pbuf = formatbuf;
- /* presume that buffer length is at least 1 */
- pbuf[0] = '%';
- len = 1;
- break;
-
- case 's':
- case 'r':
- if (PyUnicode_Check(v) && c == 's') {
- temp = v;
- Py_INCREF(temp);
- }
- else {
- PyObject *unicode;
- if (c == 's')
- temp = PyObject_Unicode(v);
- else
- temp = PyObject_Repr(v);
- if (temp == NULL)
- goto onError;
- if (PyUnicode_Check(temp))
- /* nothing to do */;
- else if (PyString_Check(temp)) {
- /* convert to string to Unicode */
- unicode = PyUnicode_Decode(PyString_AS_STRING(temp),
- PyString_GET_SIZE(temp),
- NULL,
- "strict");
- Py_DECREF(temp);
- temp = unicode;
- if (temp == NULL)
- goto onError;
- }
- else {
- Py_DECREF(temp);
- PyErr_SetString(PyExc_TypeError,
- "%s argument has non-string str()");
- goto onError;
- }
- }
- pbuf = PyUnicode_AS_UNICODE(temp);
- len = PyUnicode_GET_SIZE(temp);
- if (prec >= 0 && len > prec)
- len = prec;
- break;
-
- case 'i':
- case 'd':
- case 'u':
- case 'o':
- case 'x':
- case 'X':
- if (c == 'i')
- c = 'd';
- if (PyLong_Check(v)) {
- temp = formatlong(v, flags, prec, c);
- if (!temp)
- goto onError;
- pbuf = PyUnicode_AS_UNICODE(temp);
- len = PyUnicode_GET_SIZE(temp);
- sign = 1;
- }
- else {
- pbuf = formatbuf;
- len = formatint(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
- flags, prec, c, v);
- if (len < 0)
- goto onError;
- sign = 1;
- }
- if (flags & F_ZERO)
- fill = '0';
- break;
-
- case 'e':
- case 'E':
- case 'f':
- case 'F':
- case 'g':
- case 'G':
- if (c == 'F')
- c = 'f';
- pbuf = formatbuf;
- len = formatfloat(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
- flags, prec, c, v);
- if (len < 0)
- goto onError;
- sign = 1;
- if (flags & F_ZERO)
- fill = '0';
- break;
-
- case 'c':
- pbuf = formatbuf;
- len = formatchar(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE), v);
- if (len < 0)
- goto onError;
- break;
-
- default:
- PyErr_Format(PyExc_ValueError,
- "unsupported format character '%c' (0x%x) "
- "at index %zd",
- (31<=c && c<=126) ? (char)c : '?',
- (int)c,
- (Py_ssize_t)(fmt - 1 -
- PyUnicode_AS_UNICODE(uformat)));
- goto onError;
- }
- if (sign) {
- if (*pbuf == '-' || *pbuf == '+') {
- sign = *pbuf++;
- len--;
- }
- else if (flags & F_SIGN)
- sign = '+';
- else if (flags & F_BLANK)
- sign = ' ';
- else
- sign = 0;
- }
- if (width < len)
- width = len;
- if (rescnt - (sign != 0) < width) {
- reslen -= rescnt;
- rescnt = width + fmtcnt + 100;
- reslen += rescnt;
- if (reslen < 0) {
- Py_XDECREF(temp);
- PyErr_NoMemory();
- goto onError;
- }
- if (_PyUnicode_Resize(&result, reslen) < 0) {
- Py_XDECREF(temp);
- goto onError;
- }
- res = PyUnicode_AS_UNICODE(result)
- + reslen - rescnt;
- }
- if (sign) {
- if (fill != ' ')
- *res++ = sign;
- rescnt--;
- if (width > len)
- width--;
- }
- if ((flags & F_ALT) && (c == 'x' || c == 'X')) {
- assert(pbuf[0] == '0');
- assert(pbuf[1] == c);
- if (fill != ' ') {
- *res++ = *pbuf++;
- *res++ = *pbuf++;
- }
- rescnt -= 2;
- width -= 2;
- if (width < 0)
- width = 0;
- len -= 2;
- }
- if (width > len && !(flags & F_LJUST)) {
- do {
- --rescnt;
- *res++ = fill;
- } while (--width > len);
- }
- if (fill == ' ') {
- if (sign)
- *res++ = sign;
- if ((flags & F_ALT) && (c == 'x' || c == 'X')) {
- assert(pbuf[0] == '0');
- assert(pbuf[1] == c);
- *res++ = *pbuf++;
- *res++ = *pbuf++;
- }
- }
- Py_UNICODE_COPY(res, pbuf, len);
- res += len;
- rescnt -= len;
- while (--width >= len) {
- --rescnt;
- *res++ = ' ';
- }
- if (dict && (argidx < arglen) && c != '%') {
- PyErr_SetString(PyExc_TypeError,
- "not all arguments converted during string formatting");
- Py_XDECREF(temp);
- goto onError;
- }
- Py_XDECREF(temp);
- } /* '%' */
- } /* until end */
- if (argidx < arglen && !dict) {
- PyErr_SetString(PyExc_TypeError,
- "not all arguments converted during string formatting");
- goto onError;
- }
-
- if (_PyUnicode_Resize(&result, reslen - rescnt) < 0)
- goto onError;
- if (args_owned) {
- Py_DECREF(args);
- }
- Py_DECREF(uformat);
- return (PyObject *)result;
-
- onError:
- Py_XDECREF(result);
- Py_DECREF(uformat);
- if (args_owned) {
- Py_DECREF(args);
- }
- return NULL;
-}
-
-static PyBufferProcs unicode_as_buffer = {
- (readbufferproc) unicode_buffer_getreadbuf,
- (writebufferproc) unicode_buffer_getwritebuf,
- (segcountproc) unicode_buffer_getsegcount,
- (charbufferproc) unicode_buffer_getcharbuf,
-};
-
-static PyObject *
-unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
-
-static PyObject *
-unicode_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyObject *x = NULL;
- static char *kwlist[] = {"string", "encoding", "errors", 0};
- char *encoding = NULL;
- char *errors = NULL;
-
- if (type != &PyUnicode_Type)
- return unicode_subtype_new(type, args, kwds);
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oss:unicode",
- kwlist, &x, &encoding, &errors))
- return NULL;
- if (x == NULL)
- return (PyObject *)_PyUnicode_New(0);
- if (encoding == NULL && errors == NULL)
- return PyObject_Unicode(x);
- else
- return PyUnicode_FromEncodedObject(x, encoding, errors);
-}
-
-static PyObject *
-unicode_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- PyUnicodeObject *tmp, *pnew;
- Py_ssize_t n;
-
- assert(PyType_IsSubtype(type, &PyUnicode_Type));
- tmp = (PyUnicodeObject *)unicode_new(&PyUnicode_Type, args, kwds);
- if (tmp == NULL)
- return NULL;
- assert(PyUnicode_Check(tmp));
- pnew = (PyUnicodeObject *) type->tp_alloc(type, n = tmp->length);
- if (pnew == NULL) {
- Py_DECREF(tmp);
- return NULL;
- }
- pnew->str = PyMem_NEW(Py_UNICODE, n+1);
- if (pnew->str == NULL) {
- _Py_ForgetReference((PyObject *)pnew);
- PyObject_Del(pnew);
- Py_DECREF(tmp);
- return PyErr_NoMemory();
- }
- Py_UNICODE_COPY(pnew->str, tmp->str, n+1);
- pnew->length = n;
- pnew->hash = tmp->hash;
- Py_DECREF(tmp);
- return (PyObject *)pnew;
-}
-
-PyDoc_STRVAR(unicode_doc,
-"unicode(string [, encoding[, errors]]) -> object\n\
-\n\
-Create a new Unicode object from the given encoded string.\n\
-encoding defaults to the current default string encoding.\n\
-errors can be 'strict', 'replace' or 'ignore' and defaults to 'strict'.");
-
-PyTypeObject PyUnicode_Type = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /* ob_size */
- "unicode", /* tp_name */
- sizeof(PyUnicodeObject), /* tp_size */
- 0, /* tp_itemsize */
- /* Slots */
- (destructor)unicode_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_compare */
- unicode_repr, /* tp_repr */
- &unicode_as_number, /* tp_as_number */
- &unicode_as_sequence, /* tp_as_sequence */
- &unicode_as_mapping, /* tp_as_mapping */
- (hashfunc) unicode_hash, /* tp_hash*/
- 0, /* tp_call*/
- (reprfunc) unicode_str, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- &unicode_as_buffer, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- unicode_doc, /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- PyUnicode_RichCompare, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- unicode_methods, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- &PyBaseString_Type, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- unicode_new, /* tp_new */
- PyObject_Del, /* tp_free */
-};
-
-/* Initialize the Unicode implementation */
-
-void _PyUnicode_Init(void)
-{
- int i;
-
- /* XXX - move this array to unicodectype.c ? */
- Py_UNICODE linebreak[] = {
- 0x000A, /* LINE FEED */
- 0x000D, /* CARRIAGE RETURN */
- 0x001C, /* FILE SEPARATOR */
- 0x001D, /* GROUP SEPARATOR */
- 0x001E, /* RECORD SEPARATOR */
- 0x0085, /* NEXT LINE */
- 0x2028, /* LINE SEPARATOR */
- 0x2029, /* PARAGRAPH SEPARATOR */
- };
-
- /* Init the implementation */
- unicode_freelist = NULL;
- unicode_freelist_size = 0;
- unicode_empty = _PyUnicode_New(0);
- if (!unicode_empty)
- return;
-
- strcpy(unicode_default_encoding, "ascii");
- for (i = 0; i < 256; i++)
- unicode_latin1[i] = NULL;
- if (PyType_Ready(&PyUnicode_Type) < 0)
- Py_FatalError("Can't initialize 'unicode'");
-
- /* initialize the linebreak bloom filter */
- bloom_linebreak = make_bloom_mask(
- linebreak, sizeof(linebreak) / sizeof(linebreak[0])
- );
-
- PyType_Ready(&EncodingMapType);
-}
-
-/* Finalize the Unicode implementation */
-
-void
-_PyUnicode_Fini(void)
-{
- PyUnicodeObject *u;
- int i;
-
- Py_XDECREF(unicode_empty);
- unicode_empty = NULL;
-
- for (i = 0; i < 256; i++) {
- if (unicode_latin1[i]) {
- Py_DECREF(unicode_latin1[i]);
- unicode_latin1[i] = NULL;
- }
- }
-
- for (u = unicode_freelist; u != NULL;) {
- PyUnicodeObject *v = u;
- u = *(PyUnicodeObject **)u;
- if (v->str)
- PyMem_DEL(v->str);
- Py_XDECREF(v->defenc);
- PyObject_Del(v);
- }
- unicode_freelist = NULL;
- unicode_freelist_size = 0;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-
-/*
-Local variables:
-c-basic-offset: 4
-indent-tabs-mode: nil
-End:
-*/
diff --git a/sys/src/cmd/python/Objects/unicodetype_db.h b/sys/src/cmd/python/Objects/unicodetype_db.h
deleted file mode 100644
index 2a49a810a..000000000
--- a/sys/src/cmd/python/Objects/unicodetype_db.h
+++ /dev/null
@@ -1,1269 +0,0 @@
-/* this file was generated by Tools/unicode/makeunicodedata.py 2.5 */
-
-/* a list of unique character type descriptors */
-const _PyUnicode_TypeRecord _PyUnicode_TypeRecords[] = {
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 0},
- {0, 0, 0, 0, 0, 32},
- {0, 0, 0, 0, 0, 48},
- {0, 0, 0, 0, 0, 6},
- {0, 0, 0, 1, 1, 6},
- {0, 0, 0, 2, 2, 6},
- {0, 0, 0, 3, 3, 6},
- {0, 0, 0, 4, 4, 6},
- {0, 0, 0, 5, 5, 6},
- {0, 0, 0, 6, 6, 6},
- {0, 0, 0, 7, 7, 6},
- {0, 0, 0, 8, 8, 6},
- {0, 0, 0, 9, 9, 6},
- {0, 32, 0, 0, 0, 129},
- {65504, 0, 65504, 0, 0, 9},
- {0, 0, 0, 0, 0, 9},
- {0, 0, 0, 0, 2, 4},
- {0, 0, 0, 0, 3, 4},
- {743, 0, 743, 0, 0, 9},
- {0, 0, 0, 0, 1, 4},
- {121, 0, 121, 0, 0, 9},
- {0, 1, 0, 0, 0, 129},
- {65535, 0, 65535, 0, 0, 9},
- {0, 65337, 0, 0, 0, 129},
- {65304, 0, 65304, 0, 0, 9},
- {0, 65415, 0, 0, 0, 129},
- {65236, 0, 65236, 0, 0, 9},
- {0, 210, 0, 0, 0, 129},
- {0, 206, 0, 0, 0, 129},
- {0, 205, 0, 0, 0, 129},
- {0, 79, 0, 0, 0, 129},
- {0, 202, 0, 0, 0, 129},
- {0, 203, 0, 0, 0, 129},
- {0, 207, 0, 0, 0, 129},
- {97, 0, 97, 0, 0, 9},
- {0, 211, 0, 0, 0, 129},
- {0, 209, 0, 0, 0, 129},
- {163, 0, 163, 0, 0, 9},
- {0, 213, 0, 0, 0, 129},
- {130, 0, 130, 0, 0, 9},
- {0, 214, 0, 0, 0, 129},
- {0, 218, 0, 0, 0, 129},
- {0, 217, 0, 0, 0, 129},
- {0, 219, 0, 0, 0, 129},
- {0, 0, 0, 0, 0, 1},
- {56, 0, 56, 0, 0, 9},
- {0, 2, 1, 0, 0, 129},
- {65535, 1, 0, 0, 0, 65},
- {65534, 0, 65535, 0, 0, 9},
- {65457, 0, 65457, 0, 0, 9},
- {0, 65439, 0, 0, 0, 129},
- {0, 65480, 0, 0, 0, 129},
- {0, 65406, 0, 0, 0, 129},
- {0, 0, 0, 0, 0, 129},
- {0, 65373, 0, 0, 0, 129},
- {0, 83, 0, 0, 0, 129},
- {65326, 0, 65326, 0, 0, 9},
- {65330, 0, 65330, 0, 0, 9},
- {65331, 0, 65331, 0, 0, 9},
- {65334, 0, 65334, 0, 0, 9},
- {65333, 0, 65333, 0, 0, 9},
- {65329, 0, 65329, 0, 0, 9},
- {65327, 0, 65327, 0, 0, 9},
- {65325, 0, 65325, 0, 0, 9},
- {65323, 0, 65323, 0, 0, 9},
- {65322, 0, 65322, 0, 0, 9},
- {65318, 0, 65318, 0, 0, 9},
- {65319, 0, 65319, 0, 0, 9},
- {65317, 0, 65317, 0, 0, 9},
- {65453, 0, 65453, 0, 0, 9},
- {84, 0, 84, 0, 0, 0},
- {0, 38, 0, 0, 0, 129},
- {0, 37, 0, 0, 0, 129},
- {0, 64, 0, 0, 0, 129},
- {0, 63, 0, 0, 0, 129},
- {65498, 0, 65498, 0, 0, 9},
- {65499, 0, 65499, 0, 0, 9},
- {65505, 0, 65505, 0, 0, 9},
- {65472, 0, 65472, 0, 0, 9},
- {65473, 0, 65473, 0, 0, 9},
- {65474, 0, 65474, 0, 0, 9},
- {65479, 0, 65479, 0, 0, 9},
- {65489, 0, 65489, 0, 0, 9},
- {65482, 0, 65482, 0, 0, 9},
- {65450, 0, 65450, 0, 0, 9},
- {65456, 0, 65456, 0, 0, 9},
- {7, 0, 7, 0, 0, 9},
- {0, 65476, 0, 0, 0, 129},
- {65440, 0, 65440, 0, 0, 9},
- {0, 65529, 0, 0, 0, 129},
- {0, 80, 0, 0, 0, 129},
- {0, 48, 0, 0, 0, 129},
- {65488, 0, 65488, 0, 0, 9},
- {0, 7264, 0, 0, 0, 129},
- {0, 0, 0, 0, 4, 4},
- {0, 0, 0, 0, 5, 4},
- {0, 0, 0, 0, 6, 4},
- {0, 0, 0, 0, 7, 4},
- {0, 0, 0, 0, 8, 4},
- {0, 0, 0, 0, 9, 4},
- {65477, 0, 65477, 0, 0, 9},
- {8, 0, 8, 0, 0, 9},
- {0, 65528, 0, 0, 0, 129},
- {74, 0, 74, 0, 0, 9},
- {86, 0, 86, 0, 0, 9},
- {100, 0, 100, 0, 0, 9},
- {128, 0, 128, 0, 0, 9},
- {112, 0, 112, 0, 0, 9},
- {126, 0, 126, 0, 0, 9},
- {0, 65528, 0, 0, 0, 65},
- {9, 0, 9, 0, 0, 9},
- {0, 65462, 0, 0, 0, 129},
- {0, 65527, 0, 0, 0, 65},
- {58331, 0, 58331, 0, 0, 9},
- {0, 65450, 0, 0, 0, 129},
- {0, 65436, 0, 0, 0, 129},
- {0, 65424, 0, 0, 0, 129},
- {0, 65408, 0, 0, 0, 129},
- {0, 65410, 0, 0, 0, 129},
- {0, 0, 0, 0, 0, 4},
- {0, 58019, 0, 0, 0, 129},
- {0, 57153, 0, 0, 0, 129},
- {0, 57274, 0, 0, 0, 129},
- {0, 16, 0, 0, 0, 0},
- {65520, 0, 65520, 0, 0, 0},
- {0, 26, 0, 0, 0, 0},
- {65510, 0, 65510, 0, 0, 0},
- {58272, 0, 58272, 0, 0, 9},
- {0, 40, 0, 0, 0, 129},
- {65496, 0, 65496, 0, 0, 9},
-};
-
-/* type indexes */
-#define SHIFT 8
-static unsigned char index1[] = {
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 8, 8, 27, 28, 29, 30, 31, 32, 33, 34, 32, 35, 36,
- 32, 32, 32, 37, 38, 39, 40, 41, 42, 43, 44, 32, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 45, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 46, 21, 21, 21, 21, 47, 8, 8,
- 48, 49, 8, 8, 8, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 50, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 21, 51, 52, 21, 53, 54, 55, 56, 57,
- 8, 58, 59, 8, 8, 8, 60, 8, 61, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 62, 63, 64, 65, 66, 67, 68,
- 69, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 70,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 21, 21, 71, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 72, 73, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 74, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 74,
-};
-
-static unsigned char index2[] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 1, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 1, 1, 1, 1, 1, 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 1, 1, 1,
- 1, 1, 1, 1, 17, 18, 1, 19, 1, 1, 1, 20, 16, 1, 1, 1, 1, 1, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 1, 14, 14, 14, 14, 14, 14, 14, 16, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 15,
- 15, 15, 15, 15, 15, 15, 21, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 24, 25, 22, 23, 22, 23, 22, 23, 16, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 16, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 26, 22, 23, 22, 23, 22, 23, 27, 16, 28, 22, 23, 22, 23, 29, 22, 23,
- 30, 30, 22, 23, 16, 31, 32, 33, 22, 23, 30, 34, 35, 36, 37, 22, 23, 38,
- 16, 36, 39, 40, 41, 22, 23, 22, 23, 22, 23, 42, 22, 23, 42, 16, 16, 22,
- 23, 42, 22, 23, 43, 43, 22, 23, 22, 23, 44, 22, 23, 16, 45, 22, 23, 16,
- 46, 45, 45, 45, 45, 47, 48, 49, 47, 48, 49, 47, 48, 49, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 50, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 16, 47, 48, 49, 22,
- 23, 51, 52, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 53, 16, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 16, 16, 16, 16, 16, 16, 54, 22, 23,
- 55, 54, 16, 16, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16,
- 57, 58, 16, 59, 59, 16, 60, 16, 61, 16, 16, 16, 16, 59, 16, 16, 62, 16,
- 16, 16, 16, 63, 64, 16, 16, 16, 16, 16, 64, 16, 16, 65, 16, 16, 66, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 67, 16, 16, 67, 16, 16, 16, 16, 67,
- 16, 68, 68, 16, 16, 16, 16, 16, 16, 69, 16, 70, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 1, 1, 1, 1, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45, 45, 45, 45, 45, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 71, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
- 0, 45, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 72, 1, 73, 73, 73, 0, 74, 0, 75,
- 75, 16, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 0, 14, 14, 14, 14, 14, 14, 14, 14, 14, 76, 77, 77, 77, 16, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 78, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 79, 80, 80, 0, 81, 82, 54, 54, 54, 83, 84,
- 16, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 85, 86, 87, 16, 88, 89, 1, 22, 23, 90, 22,
- 23, 16, 54, 54, 54, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91,
- 91, 91, 91, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 86, 86, 86, 86, 86,
- 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 1, 1, 1, 1, 1, 0, 1, 1, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 54, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 0, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 0, 0, 0, 0, 0, 0, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 0, 45, 1, 1, 1, 1, 1,
- 1, 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 16, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 45,
- 45, 45, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 45, 45, 1, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 45, 45, 1, 1, 1, 1, 1, 1, 1, 45, 45, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 45, 45, 45, 1, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,
- 45, 1, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1, 1, 1, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 0, 0, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 45, 1, 1, 1, 1, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1,
- 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 45, 0, 0, 0, 1, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0,
- 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45, 0, 0,
- 0, 45, 45, 45, 45, 0, 0, 1, 45, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1,
- 1, 1, 45, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 45, 45, 0, 45, 45, 45,
- 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 45, 45, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 45, 45, 45, 45, 45, 45, 0, 0, 0,
- 0, 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45,
- 0, 45, 45, 0, 45, 45, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 0, 45, 0, 0, 0,
- 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 45, 45, 45, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45,
- 45, 0, 45, 45, 45, 45, 45, 0, 0, 1, 45, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
- 1, 0, 1, 1, 1, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45,
- 45, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45, 0,
- 0, 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45,
- 0, 45, 45, 45, 45, 45, 0, 0, 1, 45, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0,
- 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 45, 45, 0, 45, 45,
- 45, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 45, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 0, 45, 45, 45, 45, 45, 45, 0, 0,
- 0, 45, 45, 45, 0, 45, 45, 45, 45, 0, 0, 0, 45, 45, 0, 45, 0, 45, 45, 0,
- 0, 0, 45, 45, 0, 0, 0, 45, 45, 45, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45,
- 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0,
- 45, 45, 45, 45, 45, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 0,
- 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45,
- 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0,
- 45, 45, 45, 45, 45, 0, 0, 1, 45, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1,
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 45, 0, 45, 45,
- 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45, 0,
- 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1,
- 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 45, 45, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 0, 0, 45, 45, 45, 45,
- 45, 45, 45, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1,
- 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 1, 45, 45, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 45, 45,
- 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 0, 45, 0, 0,
- 45, 45, 0, 45, 0, 0, 45, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 0, 45, 45, 45,
- 45, 45, 45, 45, 0, 45, 45, 45, 0, 45, 0, 45, 0, 0, 45, 45, 0, 45, 45, 45,
- 45, 1, 45, 45, 1, 1, 1, 1, 1, 1, 0, 1, 1, 45, 0, 0, 45, 45, 45, 45, 45,
- 0, 45, 0, 1, 1, 1, 1, 1, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 0,
- 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45, 45, 45, 45, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 0,
- 45, 45, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, 1, 45, 45, 45, 45, 45, 45,
- 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1,
- 45, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0,
- 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 0, 45, 45, 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 0,
- 45, 0, 45, 45, 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 0, 0,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45,
- 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45, 0, 45, 45, 45, 45, 0, 0,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 45, 45, 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 17, 18, 95, 96, 97,
- 98, 99, 100, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 1, 1, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 1, 1, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 0, 45, 45, 45, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 45, 1, 1, 1, 1, 45, 1, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 13, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 45,
- 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45,
- 45, 45, 45, 45, 45, 45, 1, 1, 0, 0, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1,
- 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 45, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 16, 16, 16, 16, 16, 101, 0, 0, 0, 0, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22,
- 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 0, 0, 0, 0, 0, 0,
- 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103, 103, 103,
- 103, 103, 102, 102, 102, 102, 102, 102, 0, 0, 103, 103, 103, 103, 103,
- 103, 0, 0, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103, 103, 103,
- 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 102, 102, 103, 103,
- 103, 103, 103, 103, 103, 103, 102, 102, 102, 102, 102, 102, 0, 0, 103,
- 103, 103, 103, 103, 103, 0, 0, 16, 102, 16, 102, 16, 102, 16, 102, 0,
- 103, 0, 103, 0, 103, 0, 103, 102, 102, 102, 102, 102, 102, 102, 102, 103,
- 103, 103, 103, 103, 103, 103, 103, 104, 104, 105, 105, 105, 105, 106,
- 106, 107, 107, 108, 108, 109, 109, 0, 0, 102, 102, 102, 102, 102, 102,
- 102, 102, 110, 110, 110, 110, 110, 110, 110, 110, 102, 102, 102, 102,
- 102, 102, 102, 102, 110, 110, 110, 110, 110, 110, 110, 110, 102, 102,
- 102, 102, 102, 102, 102, 102, 110, 110, 110, 110, 110, 110, 110, 110,
- 102, 102, 16, 111, 16, 0, 16, 16, 103, 103, 112, 112, 113, 1, 114, 1, 1,
- 1, 16, 111, 16, 0, 16, 16, 115, 115, 115, 115, 113, 1, 1, 1, 102, 102,
- 16, 16, 0, 0, 16, 16, 103, 103, 116, 116, 0, 1, 1, 1, 102, 102, 16, 16,
- 16, 87, 16, 16, 103, 103, 117, 117, 90, 1, 1, 1, 0, 0, 16, 111, 16, 0,
- 16, 16, 118, 118, 119, 119, 113, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 1, 1, 1, 1, 1, 1, 120, 16, 0, 0, 95, 96, 97, 98, 99, 100, 1, 1, 1, 1, 1,
- 16, 120, 20, 17, 18, 95, 96, 97, 98, 99, 100, 1, 1, 1, 1, 1, 0, 45, 45,
- 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 54, 1, 1, 1, 1, 54, 1,
- 1, 16, 54, 54, 54, 16, 16, 54, 54, 54, 16, 1, 54, 1, 1, 1, 54, 54, 54,
- 54, 54, 1, 1, 1, 1, 1, 1, 54, 1, 121, 1, 54, 1, 122, 123, 54, 54, 1, 16,
- 54, 54, 1, 54, 16, 45, 45, 45, 45, 16, 1, 1, 16, 16, 54, 54, 1, 1, 1, 1,
- 1, 54, 16, 16, 16, 16, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 124, 125, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 125, 125, 125, 125, 125, 125, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 20, 17, 18, 95, 96, 97, 98, 99, 100, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 20, 17, 18, 95, 96, 97, 98, 99, 100, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 20, 17, 18, 95, 96, 97, 98, 99, 100, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126,
- 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
- 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 120, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 20, 17, 18, 95, 96, 97, 98, 99, 100, 1, 120, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1,
- 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 17, 18, 95, 96, 97, 98, 99, 100, 1,
- 20, 17, 18, 95, 96, 97, 98, 99, 100, 1, 20, 17, 18, 95, 96, 97, 98, 99,
- 100, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
- 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
- 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 0, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23, 22, 23,
- 22, 23, 22, 23, 22, 23, 22, 23, 16, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
- 128, 128, 128, 128, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45,
- 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45,
- 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0,
- 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 45, 45, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1,
- 45, 45, 1, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 0, 1, 1, 1, 1, 45, 45, 45, 1, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 45, 45, 45, 45, 0, 0, 0, 0, 0, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 45, 45, 1, 45, 45, 45, 1, 45, 45, 45, 45, 1, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16,
- 16, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 0, 0, 0,
- 0, 0, 45, 1, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 0, 45, 0, 45,
- 45, 0, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0,
- 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 1, 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 5, 6, 7, 8, 9, 10, 11,
- 12, 13, 1, 1, 1, 1, 1, 1, 1, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
- 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 1, 1, 1, 1,
- 1, 1, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0,
- 45, 45, 45, 45, 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 0, 0, 45, 45, 45,
- 45, 45, 45, 0, 0, 45, 45, 45, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
- 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 0, 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 1, 1, 1, 1, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 1, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 1, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0,
- 45, 45, 45, 45, 45, 45, 45, 45, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129, 129,
- 129, 129, 129, 129, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
- 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
- 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130,
- 130, 130, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 0, 0,
- 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 45, 45, 0, 0, 0, 45, 0, 0, 45,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 45, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 45, 45, 45, 45, 0, 45,
- 45, 45, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, 0, 0, 1, 20, 17, 18, 95, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 54, 0, 54, 54, 0, 0, 54, 0, 0,
- 54, 54, 0, 0, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 54, 54, 54, 16, 16,
- 16, 16, 0, 16, 0, 16, 16, 16, 16, 16, 16, 16, 0, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 54, 54, 0, 54, 54, 54, 54, 0, 0, 54, 54, 54, 54, 54, 54, 54,
- 54, 0, 54, 54, 54, 54, 54, 54, 54, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 54,
- 54, 0, 54, 54, 54, 54, 0, 54, 54, 54, 54, 54, 0, 54, 0, 0, 0, 54, 54, 54,
- 54, 54, 54, 54, 0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 0, 0, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 1, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 1, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 1, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 1, 16, 16, 16, 16, 16, 16, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 16, 16, 16, 16, 16, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1, 16, 16, 16, 16,
- 16, 16, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, 1, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 1,
- 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
- 45, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
-};
-
diff --git a/sys/src/cmd/python/Objects/weakrefobject.c b/sys/src/cmd/python/Objects/weakrefobject.c
deleted file mode 100644
index a404f29ad..000000000
--- a/sys/src/cmd/python/Objects/weakrefobject.c
+++ /dev/null
@@ -1,941 +0,0 @@
-#include "Python.h"
-#include "structmember.h"
-
-
-#define GET_WEAKREFS_LISTPTR(o) \
- ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
-
-
-Py_ssize_t
-_PyWeakref_GetWeakrefCount(PyWeakReference *head)
-{
- Py_ssize_t count = 0;
-
- while (head != NULL) {
- ++count;
- head = head->wr_next;
- }
- return count;
-}
-
-
-static void
-init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
-{
- self->hash = -1;
- self->wr_object = ob;
- Py_XINCREF(callback);
- self->wr_callback = callback;
-}
-
-static PyWeakReference *
-new_weakref(PyObject *ob, PyObject *callback)
-{
- PyWeakReference *result;
-
- result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
- if (result) {
- init_weakref(result, ob, callback);
- PyObject_GC_Track(result);
- }
- return result;
-}
-
-
-/* This function clears the passed-in reference and removes it from the
- * list of weak references for the referent. This is the only code that
- * removes an item from the doubly-linked list of weak references for an
- * object; it is also responsible for clearing the callback slot.
- */
-static void
-clear_weakref(PyWeakReference *self)
-{
- PyObject *callback = self->wr_callback;
-
- if (PyWeakref_GET_OBJECT(self) != Py_None) {
- PyWeakReference **list = GET_WEAKREFS_LISTPTR(
- PyWeakref_GET_OBJECT(self));
-
- if (*list == self)
- /* If 'self' is the end of the list (and thus self->wr_next == NULL)
- then the weakref list itself (and thus the value of *list) will
- end up being set to NULL. */
- *list = self->wr_next;
- self->wr_object = Py_None;
- if (self->wr_prev != NULL)
- self->wr_prev->wr_next = self->wr_next;
- if (self->wr_next != NULL)
- self->wr_next->wr_prev = self->wr_prev;
- self->wr_prev = NULL;
- self->wr_next = NULL;
- }
- if (callback != NULL) {
- Py_DECREF(callback);
- self->wr_callback = NULL;
- }
-}
-
-/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
- * the callback intact and uncalled. It must be possible to call self's
- * tp_dealloc() after calling this, so self has to be left in a sane enough
- * state for that to work. We expect tp_dealloc to decref the callback
- * then. The reason for not letting clear_weakref() decref the callback
- * right now is that if the callback goes away, that may in turn trigger
- * another callback (if a weak reference to the callback exists) -- running
- * arbitrary Python code in the middle of gc is a disaster. The convolution
- * here allows gc to delay triggering such callbacks until the world is in
- * a sane state again.
- */
-void
-_PyWeakref_ClearRef(PyWeakReference *self)
-{
- PyObject *callback;
-
- assert(self != NULL);
- assert(PyWeakref_Check(self));
- /* Preserve and restore the callback around clear_weakref. */
- callback = self->wr_callback;
- self->wr_callback = NULL;
- clear_weakref(self);
- self->wr_callback = callback;
-}
-
-static void
-weakref_dealloc(PyObject *self)
-{
- PyObject_GC_UnTrack(self);
- clear_weakref((PyWeakReference *) self);
- self->ob_type->tp_free(self);
-}
-
-
-static int
-gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
-{
- Py_VISIT(self->wr_callback);
- return 0;
-}
-
-
-static int
-gc_clear(PyWeakReference *self)
-{
- clear_weakref(self);
- return 0;
-}
-
-
-static PyObject *
-weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
-{
- static char *kwlist[] = {NULL};
-
- if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
- PyObject *object = PyWeakref_GET_OBJECT(self);
- Py_INCREF(object);
- return (object);
- }
- return NULL;
-}
-
-
-static long
-weakref_hash(PyWeakReference *self)
-{
- if (self->hash != -1)
- return self->hash;
- if (PyWeakref_GET_OBJECT(self) == Py_None) {
- PyErr_SetString(PyExc_TypeError, "weak object has gone away");
- return -1;
- }
- self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
- return self->hash;
-}
-
-
-static PyObject *
-weakref_repr(PyWeakReference *self)
-{
- char buffer[256];
- if (PyWeakref_GET_OBJECT(self) == Py_None) {
- PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
- }
- else {
- char *name = NULL;
- PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
- "__name__");
- if (nameobj == NULL)
- PyErr_Clear();
- else if (PyString_Check(nameobj))
- name = PyString_AS_STRING(nameobj);
- PyOS_snprintf(buffer, sizeof(buffer),
- name ? "<weakref at %p; to '%.50s' at %p (%s)>"
- : "<weakref at %p; to '%.50s' at %p>",
- self,
- PyWeakref_GET_OBJECT(self)->ob_type->tp_name,
- PyWeakref_GET_OBJECT(self),
- name);
- Py_XDECREF(nameobj);
- }
- return PyString_FromString(buffer);
-}
-
-/* Weak references only support equality, not ordering. Two weak references
- are equal if the underlying objects are equal. If the underlying object has
- gone away, they are equal if they are identical. */
-
-static PyObject *
-weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
-{
- if (op != Py_EQ || self->ob_type != other->ob_type) {
- Py_INCREF(Py_NotImplemented);
- return Py_NotImplemented;
- }
- if (PyWeakref_GET_OBJECT(self) == Py_None
- || PyWeakref_GET_OBJECT(other) == Py_None) {
- PyObject *res = self==other ? Py_True : Py_False;
- Py_INCREF(res);
- return res;
- }
- return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
- PyWeakref_GET_OBJECT(other), op);
-}
-
-/* Given the head of an object's list of weak references, extract the
- * two callback-less refs (ref and proxy). Used to determine if the
- * shared references exist and to determine the back link for newly
- * inserted references.
- */
-static void
-get_basic_refs(PyWeakReference *head,
- PyWeakReference **refp, PyWeakReference **proxyp)
-{
- *refp = NULL;
- *proxyp = NULL;
-
- if (head != NULL && head->wr_callback == NULL) {
- /* We need to be careful that the "basic refs" aren't
- subclasses of the main types. That complicates this a
- little. */
- if (PyWeakref_CheckRefExact(head)) {
- *refp = head;
- head = head->wr_next;
- }
- if (head != NULL
- && head->wr_callback == NULL
- && PyWeakref_CheckProxy(head)) {
- *proxyp = head;
- /* head = head->wr_next; */
- }
- }
-}
-
-/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
-static void
-insert_after(PyWeakReference *newref, PyWeakReference *prev)
-{
- newref->wr_prev = prev;
- newref->wr_next = prev->wr_next;
- if (prev->wr_next != NULL)
- prev->wr_next->wr_prev = newref;
- prev->wr_next = newref;
-}
-
-/* Insert 'newref' at the head of the list; 'list' points to the variable
- * that stores the head.
- */
-static void
-insert_head(PyWeakReference *newref, PyWeakReference **list)
-{
- PyWeakReference *next = *list;
-
- newref->wr_prev = NULL;
- newref->wr_next = next;
- if (next != NULL)
- next->wr_prev = newref;
- *list = newref;
-}
-
-static int
-parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
- PyObject **obp, PyObject **callbackp)
-{
- /* XXX Should check that kwargs == NULL or is empty. */
- return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
-}
-
-static PyObject *
-weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
-{
- PyWeakReference *self = NULL;
- PyObject *ob, *callback = NULL;
-
- if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
- PyWeakReference *ref, *proxy;
- PyWeakReference **list;
-
- if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
- PyErr_Format(PyExc_TypeError,
- "cannot create weak reference to '%s' object",
- ob->ob_type->tp_name);
- return NULL;
- }
- if (callback == Py_None)
- callback = NULL;
- list = GET_WEAKREFS_LISTPTR(ob);
- get_basic_refs(*list, &ref, &proxy);
- if (callback == NULL && type == &_PyWeakref_RefType) {
- if (ref != NULL) {
- /* We can re-use an existing reference. */
- Py_INCREF(ref);
- return (PyObject *)ref;
- }
- }
- /* We have to create a new reference. */
- /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
- list on ob can be mutated. This means that the ref and
- proxy pointers we got back earlier may have been collected,
- so we need to compute these values again before we use
- them. */
- self = (PyWeakReference *) (type->tp_alloc(type, 0));
- if (self != NULL) {
- init_weakref(self, ob, callback);
- if (callback == NULL && type == &_PyWeakref_RefType) {
- insert_head(self, list);
- }
- else {
- PyWeakReference *prev;
-
- get_basic_refs(*list, &ref, &proxy);
- prev = (proxy == NULL) ? ref : proxy;
- if (prev == NULL)
- insert_head(self, list);
- else
- insert_after(self, prev);
- }
- }
- }
- return (PyObject *)self;
-}
-
-static int
-weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
-{
- PyObject *tmp;
-
- if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
- return 0;
- else
- return 1;
-}
-
-
-PyTypeObject
-_PyWeakref_RefType = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "weakref",
- sizeof(PyWeakReference),
- 0,
- weakref_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- 0, /*tp_getattr*/
- 0, /*tp_setattr*/
- 0, /*tp_compare*/
- (reprfunc)weakref_repr, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- (hashfunc)weakref_hash, /*tp_hash*/
- (ternaryfunc)weakref_call, /*tp_call*/
- 0, /*tp_str*/
- 0, /*tp_getattro*/
- 0, /*tp_setattro*/
- 0, /*tp_as_buffer*/
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
- | Py_TPFLAGS_BASETYPE, /*tp_flags*/
- 0, /*tp_doc*/
- (traverseproc)gc_traverse, /*tp_traverse*/
- (inquiry)gc_clear, /*tp_clear*/
- (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
- 0, /*tp_weaklistoffset*/
- 0, /*tp_iter*/
- 0, /*tp_iternext*/
- 0, /*tp_methods*/
- 0, /*tp_members*/
- 0, /*tp_getset*/
- 0, /*tp_base*/
- 0, /*tp_dict*/
- 0, /*tp_descr_get*/
- 0, /*tp_descr_set*/
- 0, /*tp_dictoffset*/
- weakref___init__, /*tp_init*/
- PyType_GenericAlloc, /*tp_alloc*/
- weakref___new__, /*tp_new*/
- PyObject_GC_Del, /*tp_free*/
-};
-
-
-static int
-proxy_checkref(PyWeakReference *proxy)
-{
- if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
- PyErr_SetString(PyExc_ReferenceError,
- "weakly-referenced object no longer exists");
- return 0;
- }
- return 1;
-}
-
-
-/* If a parameter is a proxy, check that it is still "live" and wrap it,
- * replacing the original value with the raw object. Raises ReferenceError
- * if the param is a dead proxy.
- */
-#define UNWRAP(o) \
- if (PyWeakref_CheckProxy(o)) { \
- if (!proxy_checkref((PyWeakReference *)o)) \
- return NULL; \
- o = PyWeakref_GET_OBJECT(o); \
- }
-
-#define UNWRAP_I(o) \
- if (PyWeakref_CheckProxy(o)) { \
- if (!proxy_checkref((PyWeakReference *)o)) \
- return -1; \
- o = PyWeakref_GET_OBJECT(o); \
- }
-
-#define WRAP_UNARY(method, generic) \
- static PyObject * \
- method(PyObject *proxy) { \
- UNWRAP(proxy); \
- return generic(proxy); \
- }
-
-#define WRAP_BINARY(method, generic) \
- static PyObject * \
- method(PyObject *x, PyObject *y) { \
- UNWRAP(x); \
- UNWRAP(y); \
- return generic(x, y); \
- }
-
-/* Note that the third arg needs to be checked for NULL since the tp_call
- * slot can receive NULL for this arg.
- */
-#define WRAP_TERNARY(method, generic) \
- static PyObject * \
- method(PyObject *proxy, PyObject *v, PyObject *w) { \
- UNWRAP(proxy); \
- UNWRAP(v); \
- if (w != NULL) \
- UNWRAP(w); \
- return generic(proxy, v, w); \
- }
-
-
-/* direct slots */
-
-WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
-WRAP_UNARY(proxy_str, PyObject_Str)
-WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
-
-static PyObject *
-proxy_repr(PyWeakReference *proxy)
-{
- char buf[160];
- PyOS_snprintf(buf, sizeof(buf),
- "<weakproxy at %p to %.100s at %p>", proxy,
- PyWeakref_GET_OBJECT(proxy)->ob_type->tp_name,
- PyWeakref_GET_OBJECT(proxy));
- return PyString_FromString(buf);
-}
-
-
-static int
-proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
-{
- if (!proxy_checkref(proxy))
- return -1;
- return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
-}
-
-static int
-proxy_compare(PyObject *proxy, PyObject *v)
-{
- UNWRAP_I(proxy);
- UNWRAP_I(v);
- return PyObject_Compare(proxy, v);
-}
-
-/* number slots */
-WRAP_BINARY(proxy_add, PyNumber_Add)
-WRAP_BINARY(proxy_sub, PyNumber_Subtract)
-WRAP_BINARY(proxy_mul, PyNumber_Multiply)
-WRAP_BINARY(proxy_div, PyNumber_Divide)
-WRAP_BINARY(proxy_mod, PyNumber_Remainder)
-WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
-WRAP_TERNARY(proxy_pow, PyNumber_Power)
-WRAP_UNARY(proxy_neg, PyNumber_Negative)
-WRAP_UNARY(proxy_pos, PyNumber_Positive)
-WRAP_UNARY(proxy_abs, PyNumber_Absolute)
-WRAP_UNARY(proxy_invert, PyNumber_Invert)
-WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
-WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
-WRAP_BINARY(proxy_and, PyNumber_And)
-WRAP_BINARY(proxy_xor, PyNumber_Xor)
-WRAP_BINARY(proxy_or, PyNumber_Or)
-WRAP_UNARY(proxy_int, PyNumber_Int)
-WRAP_UNARY(proxy_long, PyNumber_Long)
-WRAP_UNARY(proxy_float, PyNumber_Float)
-WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
-WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
-WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
-WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
-WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
-WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
-WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
-WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
-WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
-WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
-WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
-
-static int
-proxy_nonzero(PyWeakReference *proxy)
-{
- PyObject *o = PyWeakref_GET_OBJECT(proxy);
- if (!proxy_checkref(proxy))
- return -1;
- return PyObject_IsTrue(o);
-}
-
-static void
-proxy_dealloc(PyWeakReference *self)
-{
- if (self->wr_callback != NULL)
- PyObject_GC_UnTrack((PyObject *)self);
- clear_weakref(self);
- PyObject_GC_Del(self);
-}
-
-/* sequence slots */
-
-static PyObject *
-proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
-{
- if (!proxy_checkref(proxy))
- return NULL;
- return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
-}
-
-static int
-proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
-{
- if (!proxy_checkref(proxy))
- return -1;
- return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
-}
-
-static int
-proxy_contains(PyWeakReference *proxy, PyObject *value)
-{
- if (!proxy_checkref(proxy))
- return -1;
- return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
-}
-
-
-/* mapping slots */
-
-static Py_ssize_t
-proxy_length(PyWeakReference *proxy)
-{
- if (!proxy_checkref(proxy))
- return -1;
- return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
-}
-
-WRAP_BINARY(proxy_getitem, PyObject_GetItem)
-
-static int
-proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
-{
- if (!proxy_checkref(proxy))
- return -1;
-
- if (value == NULL)
- return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
- else
- return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
-}
-
-/* iterator slots */
-
-static PyObject *
-proxy_iter(PyWeakReference *proxy)
-{
- if (!proxy_checkref(proxy))
- return NULL;
- return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
-}
-
-static PyObject *
-proxy_iternext(PyWeakReference *proxy)
-{
- if (!proxy_checkref(proxy))
- return NULL;
- return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
-}
-
-
-static PyNumberMethods proxy_as_number = {
- proxy_add, /*nb_add*/
- proxy_sub, /*nb_subtract*/
- proxy_mul, /*nb_multiply*/
- proxy_div, /*nb_divide*/
- proxy_mod, /*nb_remainder*/
- proxy_divmod, /*nb_divmod*/
- proxy_pow, /*nb_power*/
- proxy_neg, /*nb_negative*/
- proxy_pos, /*nb_positive*/
- proxy_abs, /*nb_absolute*/
- (inquiry)proxy_nonzero, /*nb_nonzero*/
- proxy_invert, /*nb_invert*/
- proxy_lshift, /*nb_lshift*/
- proxy_rshift, /*nb_rshift*/
- proxy_and, /*nb_and*/
- proxy_xor, /*nb_xor*/
- proxy_or, /*nb_or*/
- 0, /*nb_coerce*/
- proxy_int, /*nb_int*/
- proxy_long, /*nb_long*/
- proxy_float, /*nb_float*/
- 0, /*nb_oct*/
- 0, /*nb_hex*/
- proxy_iadd, /*nb_inplace_add*/
- proxy_isub, /*nb_inplace_subtract*/
- proxy_imul, /*nb_inplace_multiply*/
- proxy_idiv, /*nb_inplace_divide*/
- proxy_imod, /*nb_inplace_remainder*/
- proxy_ipow, /*nb_inplace_power*/
- proxy_ilshift, /*nb_inplace_lshift*/
- proxy_irshift, /*nb_inplace_rshift*/
- proxy_iand, /*nb_inplace_and*/
- proxy_ixor, /*nb_inplace_xor*/
- proxy_ior, /*nb_inplace_or*/
-};
-
-static PySequenceMethods proxy_as_sequence = {
- (lenfunc)proxy_length, /*sq_length*/
- 0, /*sq_concat*/
- 0, /*sq_repeat*/
- 0, /*sq_item*/
- (ssizessizeargfunc)proxy_slice, /*sq_slice*/
- 0, /*sq_ass_item*/
- (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
- (objobjproc)proxy_contains, /* sq_contains */
-};
-
-static PyMappingMethods proxy_as_mapping = {
- (lenfunc)proxy_length, /*mp_length*/
- proxy_getitem, /*mp_subscript*/
- (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
-};
-
-
-PyTypeObject
-_PyWeakref_ProxyType = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "weakproxy",
- sizeof(PyWeakReference),
- 0,
- /* methods */
- (destructor)proxy_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- proxy_compare, /* tp_compare */
- (reprfunc)proxy_repr, /* tp_repr */
- &proxy_as_number, /* tp_as_number */
- &proxy_as_sequence, /* tp_as_sequence */
- &proxy_as_mapping, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- proxy_str, /* tp_str */
- proxy_getattr, /* tp_getattro */
- (setattrofunc)proxy_setattr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
- | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)gc_traverse, /* tp_traverse */
- (inquiry)gc_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- (getiterfunc)proxy_iter, /* tp_iter */
- (iternextfunc)proxy_iternext, /* tp_iternext */
-};
-
-
-PyTypeObject
-_PyWeakref_CallableProxyType = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0,
- "weakcallableproxy",
- sizeof(PyWeakReference),
- 0,
- /* methods */
- (destructor)proxy_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- proxy_compare, /* tp_compare */
- (unaryfunc)proxy_repr, /* tp_repr */
- &proxy_as_number, /* tp_as_number */
- &proxy_as_sequence, /* tp_as_sequence */
- &proxy_as_mapping, /* tp_as_mapping */
- 0, /* tp_hash */
- proxy_call, /* tp_call */
- proxy_str, /* tp_str */
- proxy_getattr, /* tp_getattro */
- (setattrofunc)proxy_setattr, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
- | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)gc_traverse, /* tp_traverse */
- (inquiry)gc_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- (getiterfunc)proxy_iter, /* tp_iter */
- (iternextfunc)proxy_iternext, /* tp_iternext */
-};
-
-
-
-PyObject *
-PyWeakref_NewRef(PyObject *ob, PyObject *callback)
-{
- PyWeakReference *result = NULL;
- PyWeakReference **list;
- PyWeakReference *ref, *proxy;
-
- if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
- PyErr_Format(PyExc_TypeError,
- "cannot create weak reference to '%s' object",
- ob->ob_type->tp_name);
- return NULL;
- }
- list = GET_WEAKREFS_LISTPTR(ob);
- get_basic_refs(*list, &ref, &proxy);
- if (callback == Py_None)
- callback = NULL;
- if (callback == NULL)
- /* return existing weak reference if it exists */
- result = ref;
- if (result != NULL)
- Py_INCREF(result);
- else {
- /* Note: new_weakref() can trigger cyclic GC, so the weakref
- list on ob can be mutated. This means that the ref and
- proxy pointers we got back earlier may have been collected,
- so we need to compute these values again before we use
- them. */
- result = new_weakref(ob, callback);
- if (result != NULL) {
- get_basic_refs(*list, &ref, &proxy);
- if (callback == NULL) {
- if (ref == NULL)
- insert_head(result, list);
- else {
- /* Someone else added a ref without a callback
- during GC. Return that one instead of this one
- to avoid violating the invariants of the list
- of weakrefs for ob. */
- Py_DECREF(result);
- Py_INCREF(ref);
- result = ref;
- }
- }
- else {
- PyWeakReference *prev;
-
- prev = (proxy == NULL) ? ref : proxy;
- if (prev == NULL)
- insert_head(result, list);
- else
- insert_after(result, prev);
- }
- }
- }
- return (PyObject *) result;
-}
-
-
-PyObject *
-PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
-{
- PyWeakReference *result = NULL;
- PyWeakReference **list;
- PyWeakReference *ref, *proxy;
-
- if (!PyType_SUPPORTS_WEAKREFS(ob->ob_type)) {
- PyErr_Format(PyExc_TypeError,
- "cannot create weak reference to '%s' object",
- ob->ob_type->tp_name);
- return NULL;
- }
- list = GET_WEAKREFS_LISTPTR(ob);
- get_basic_refs(*list, &ref, &proxy);
- if (callback == Py_None)
- callback = NULL;
- if (callback == NULL)
- /* attempt to return an existing weak reference if it exists */
- result = proxy;
- if (result != NULL)
- Py_INCREF(result);
- else {
- /* Note: new_weakref() can trigger cyclic GC, so the weakref
- list on ob can be mutated. This means that the ref and
- proxy pointers we got back earlier may have been collected,
- so we need to compute these values again before we use
- them. */
- result = new_weakref(ob, callback);
- if (result != NULL) {
- PyWeakReference *prev;
-
- if (PyCallable_Check(ob))
- result->ob_type = &_PyWeakref_CallableProxyType;
- else
- result->ob_type = &_PyWeakref_ProxyType;
- get_basic_refs(*list, &ref, &proxy);
- if (callback == NULL) {
- if (proxy != NULL) {
- /* Someone else added a proxy without a callback
- during GC. Return that one instead of this one
- to avoid violating the invariants of the list
- of weakrefs for ob. */
- Py_DECREF(result);
- Py_INCREF(result = proxy);
- goto skip_insert;
- }
- prev = ref;
- }
- else
- prev = (proxy == NULL) ? ref : proxy;
-
- if (prev == NULL)
- insert_head(result, list);
- else
- insert_after(result, prev);
- skip_insert:
- ;
- }
- }
- return (PyObject *) result;
-}
-
-
-PyObject *
-PyWeakref_GetObject(PyObject *ref)
-{
- if (ref == NULL || !PyWeakref_Check(ref)) {
- PyErr_BadInternalCall();
- return NULL;
- }
- return PyWeakref_GET_OBJECT(ref);
-}
-
-/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
- * handle_weakrefs().
- */
-static void
-handle_callback(PyWeakReference *ref, PyObject *callback)
-{
- PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
-
- if (cbresult == NULL)
- PyErr_WriteUnraisable(callback);
- else
- Py_DECREF(cbresult);
-}
-
-/* This function is called by the tp_dealloc handler to clear weak references.
- *
- * This iterates through the weak references for 'object' and calls callbacks
- * for those references which have one. It returns when all callbacks have
- * been attempted.
- */
-void
-PyObject_ClearWeakRefs(PyObject *object)
-{
- PyWeakReference **list;
-
- if (object == NULL
- || !PyType_SUPPORTS_WEAKREFS(object->ob_type)
- || object->ob_refcnt != 0) {
- PyErr_BadInternalCall();
- return;
- }
- list = GET_WEAKREFS_LISTPTR(object);
- /* Remove the callback-less basic and proxy references */
- if (*list != NULL && (*list)->wr_callback == NULL) {
- clear_weakref(*list);
- if (*list != NULL && (*list)->wr_callback == NULL)
- clear_weakref(*list);
- }
- if (*list != NULL) {
- PyWeakReference *current = *list;
- Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
- int restore_error = PyErr_Occurred() ? 1 : 0;
- PyObject *err_type, *err_value, *err_tb;
-
- if (restore_error)
- PyErr_Fetch(&err_type, &err_value, &err_tb);
- if (count == 1) {
- PyObject *callback = current->wr_callback;
-
- current->wr_callback = NULL;
- clear_weakref(current);
- if (callback != NULL) {
- handle_callback(current, callback);
- Py_DECREF(callback);
- }
- }
- else {
- PyObject *tuple;
- Py_ssize_t i = 0;
-
- tuple = PyTuple_New(count * 2);
- if (tuple == NULL) {
- if (restore_error)
- PyErr_Fetch(&err_type, &err_value, &err_tb);
- return;
- }
-
- for (i = 0; i < count; ++i) {
- PyWeakReference *next = current->wr_next;
-
- Py_INCREF(current);
- PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
- PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
- current->wr_callback = NULL;
- clear_weakref(current);
- current = next;
- }
- for (i = 0; i < count; ++i) {
- PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
-
- if (callback != NULL) {
- PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
- handle_callback((PyWeakReference *)item, callback);
- }
- }
- Py_DECREF(tuple);
- }
- if (restore_error)
- PyErr_Restore(err_type, err_value, err_tb);
- }
-}