]> granicus.if.org Git - python/commitdiff
A bunch of functions are now properly implemented in abstract.c, and
authorGuido van Rossum <guido@python.org>
Fri, 22 May 1998 00:51:39 +0000 (00:51 +0000)
committerGuido van Rossum <guido@python.org>
Fri, 22 May 1998 00:51:39 +0000 (00:51 +0000)
the code here becomes much simpler.  In particular: abs(), divmod(),
pow(), int(), long(), float(), len(), tuple(), list().

Also make sure that no use of a function pointer gotten from a
tp_as_sequence or tp_as_mapping structure is made without checking it
for NULL first.

A few other cosmetic things, such as properly reindenting slice().

Python/bltinmodule.c

index 68a5109660262e236bdf91e6a29e33e6603cbf41..7ca72ed4c5144fa2dcec500b944865906db5b9fd 100644 (file)
@@ -48,9 +48,6 @@ PERFORMANCE OF THIS SOFTWARE.
 /* Forward */
 static PyObject *filterstring Py_PROTO((PyObject *, PyObject *));
 static PyObject *filtertuple  Py_PROTO((PyObject *, PyObject *));
-static PyObject *int_from_string Py_PROTO((PyObject *));
-static PyObject *long_from_string Py_PROTO((PyObject *));
-static PyObject *float_from_string Py_PROTO((PyObject *));
 
 static PyObject *
 builtin___import__(self, args)
@@ -75,16 +72,10 @@ builtin_abs(self, args)
        PyObject *args;
 {
        PyObject *v;
-       PyNumberMethods *nm;
 
        if (!PyArg_ParseTuple(args, "O:abs", &v))
                return NULL;
-       if ((nm = v->ob_type->tp_as_number) == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                               "abs() requires numeric argument");
-               return NULL;
-       }
-       return (*nm->nb_absolute)(v);
+       return PyNumber_Absolute(v);
 }
 
 static PyObject *
@@ -144,7 +135,8 @@ builtin_filter(self, args)
                return r;
        }
 
-       if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
+       sqf = seq->ob_type->tp_as_sequence;
+       if (sqf == NULL || sqf->sq_length == NULL || sqf->sq_item == NULL) {
                PyErr_SetString(PyExc_TypeError,
                           "argument 2 to filter() must be a sequence type");
                goto Fail_2;
@@ -245,14 +237,13 @@ builtin_cmp(self, args)
        PyObject *args;
 {
        PyObject *a, *b;
-       long c;
+       int c;
 
        if (!PyArg_ParseTuple(args, "OO:cmp", &a, &b))
                return NULL;
-       c = PyObject_Compare(a, b);
-       if (c && PyErr_Occurred())
+       if (PyObject_Cmp(a, b, &c) < 0)
                return NULL;
-       return PyInt_FromLong(c);
+       return PyInt_FromLong((long)c);
 }
 
 static PyObject *
@@ -450,29 +441,6 @@ builtin_dir(self, args)
        return NULL;
 }
 
-static PyObject *
-do_divmod(v, w)
-       PyObject *v, *w;
-{
-       PyObject *res;
-
-       if (PyInstance_Check(v) || PyInstance_Check(w))
-               return PyInstance_DoBinOp(v, w, "__divmod__", "__rdivmod__",
-                                    do_divmod);
-       if (v->ob_type->tp_as_number == NULL ||
-                               w->ob_type->tp_as_number == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                   "divmod() requires numeric or class instance arguments");
-               return NULL;
-       }
-       if (PyNumber_Coerce(&v, &w) != 0)
-               return NULL;
-       res = (*v->ob_type->tp_as_number->nb_divmod)(v, w);
-       Py_DECREF(v);
-       Py_DECREF(w);
-       return res;
-}
-
 static PyObject *
 builtin_divmod(self, args)
        PyObject *self;
@@ -482,7 +450,7 @@ builtin_divmod(self, args)
 
        if (!PyArg_ParseTuple(args, "OO:divmod", &v, &w))
                return NULL;
-       return do_divmod(v, w);
+       return PyNumber_Divmod(v, w);
 }
 
 static PyObject *
@@ -576,19 +544,10 @@ builtin_float(self, args)
        PyObject *args;
 {
        PyObject *v;
-       PyNumberMethods *nb;
 
        if (!PyArg_ParseTuple(args, "O:float", &v))
                return NULL;
-       if (PyString_Check(v))
-               return float_from_string(v);
-       if ((nb = v->ob_type->tp_as_number) == NULL ||
-           nb->nb_float == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                          "float() argument can't be converted to float");
-               return NULL;
-       }
-       return (*nb->nb_float)(v);
+       return PyNumber_Float(v);
 }
 
 static PyObject *
@@ -631,10 +590,12 @@ builtin_hasattr(self, args)
        v = PyObject_GetAttr(v, name);
        if (v == NULL) {
                PyErr_Clear();
-               return PyInt_FromLong(0L);
+               Py_INCREF(Py_False);
+               return Py_False;
        }
        Py_DECREF(v);
-       return PyInt_FromLong(1L);
+       Py_INCREF(Py_True);
+       return Py_True;
 }
 
 static PyObject *
@@ -682,11 +643,16 @@ builtin_map(self, args)
 
        for (len = 0, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
                int curlen;
+               PySequenceMethods *sqf;
        
                if ((sqp->seq = PyTuple_GetItem(args, i + 1)) == NULL)
                        goto Fail_2;
 
-               if (! (sqp->sqf = sqp->seq->ob_type->tp_as_sequence)) {
+               sqp->sqf = sqf = sqp->seq->ob_type->tp_as_sequence;
+               if (sqf == NULL ||
+                   sqf->sq_length == NULL ||
+                   sqf->sq_item == NULL)
+               {
                        static char errmsg[] =
                            "argument %d to map() must be a sequence object";
                        char errbuf[sizeof(errmsg) + 25];
@@ -916,15 +882,7 @@ builtin_int(self, args)
 
        if (!PyArg_ParseTuple(args, "O:int", &v))
                return NULL;
-       if (PyString_Check(v))
-               return int_from_string(v);
-       if ((nb = v->ob_type->tp_as_number) == NULL ||
-           nb->nb_int == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                          "int() argument can't be converted to int");
-               return NULL;
-       }
-       return (*nb->nb_int)(v);
+       return PyNumber_Int(v);
 }
 
 static PyObject *
@@ -933,26 +891,10 @@ builtin_len(self, args)
        PyObject *args;
 {
        PyObject *v;
-       long len;
-       PyTypeObject *tp;
 
        if (!PyArg_ParseTuple(args, "O:len", &v))
                return NULL;
-       tp = v->ob_type;
-       if (tp->tp_as_sequence != NULL) {
-               len = (*tp->tp_as_sequence->sq_length)(v);
-       }
-       else if (tp->tp_as_mapping != NULL) {
-               len = (*tp->tp_as_mapping->mp_length)(v);
-       }
-       else {
-               PyErr_SetString(PyExc_TypeError, "len() of unsized object");
-               return NULL;
-       }
-       if (len < 0)
-               return NULL;
-       else
-               return PyInt_FromLong(len);
+       return PyInt_FromLong((long)PyObject_Length(v));
 }
 
 static PyObject *
@@ -961,33 +903,10 @@ builtin_list(self, args)
        PyObject *args;
 {
        PyObject *v;
-       PySequenceMethods *sqf;
 
        if (!PyArg_ParseTuple(args, "O:list", &v))
                return NULL;
-       if ((sqf = v->ob_type->tp_as_sequence) != NULL) {
-               int n = (*sqf->sq_length)(v);
-               int i;
-               PyObject *l;
-               if (n < 0)
-                       return NULL;
-               l = PyList_New(n);
-               if (l == NULL)
-                       return NULL;
-               for (i = 0; i < n; i++) {
-                       PyObject *item = (*sqf->sq_item)(v, i);
-                       if (item == NULL) {
-                               Py_DECREF(l);
-                               l = NULL;
-                               break;
-                       }
-                       PyList_SetItem(l, i, item);
-               }
-               /* XXX Should support indefinite-length sequences */
-               return l;
-       }
-       PyErr_SetString(PyExc_TypeError, "list() argument must be a sequence");
-       return NULL;
+       return PySequence_List(v);
 }
 
 
@@ -996,20 +915,20 @@ builtin_slice(self, args)
      PyObject *self;
      PyObject *args;
 {
-  PyObject *start, *stop, *step;
+       PyObject *start, *stop, *step;
 
-  start = stop = step = NULL;
+       start = stop = step = NULL;
 
-  if (!PyArg_ParseTuple(args, "O|OO:slice", &start, &stop, &step))
-    return NULL;
+       if (!PyArg_ParseTuple(args, "O|OO:slice", &start, &stop, &step))
+               return NULL;
 
-  /*This swapping of stop and start is to maintain compatibility with
-    the range builtin.*/
-  if (stop == NULL) {
-    stop = start;
-    start = NULL;
-  }
-  return PySlice_New(start, stop, step);
+       /* 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);
 }
 
 static PyObject *
@@ -1032,19 +951,10 @@ builtin_long(self, args)
        PyObject *args;
 {
        PyObject *v;
-       PyNumberMethods *nb;
        
        if (!PyArg_ParseTuple(args, "O:long", &v))
                return NULL;
-       if (PyString_Check(v))
-               return long_from_string(v);
-       if ((nb = v->ob_type->tp_as_number) == NULL ||
-           nb->nb_long == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                          "long() argument can't be converted to long");
-               return NULL;
-       }
-       return (*nb->nb_long)(v);
+       return PyNumber_Long(v);
 }
 
 static PyObject *
@@ -1061,7 +971,7 @@ min_max(args, sign)
        else if (!PyArg_ParseTuple(args, "O:min/max", &v))
                return NULL;
        sq = v->ob_type->tp_as_sequence;
-       if (sq == NULL) {
+       if (sq == NULL || sq->sq_item == NULL) {
                PyErr_SetString(PyExc_TypeError,
                                "min() or max() of non-sequence");
                return NULL;
@@ -1165,80 +1075,16 @@ builtin_ord(self, args)
        return PyInt_FromLong((long)(c & 0xff));
 }
 
-static PyObject *
-do_pow(v, w)
-       PyObject *v, *w;
-{
-       PyObject *res;
-       if (PyInstance_Check(v) || PyInstance_Check(w))
-               return PyInstance_DoBinOp(v, w, "__pow__", "__rpow__", do_pow);
-       if (v->ob_type->tp_as_number == NULL ||
-           w->ob_type->tp_as_number == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                               "pow() requires numeric arguments");
-               return NULL;
-       }
-       if (
-#ifndef WITHOUT_COMPLEX
-            !PyComplex_Check(v) && 
-#endif
-            PyFloat_Check(w) && PyFloat_AsDouble(v) < 0.0) {
-               if (!PyErr_Occurred())
-                   PyErr_SetString(PyExc_ValueError,
-                                   "negative number to float power");
-               return NULL;
-       }
-       if (PyNumber_Coerce(&v, &w) != 0)
-               return NULL;
-       res = (*v->ob_type->tp_as_number->nb_power)(v, w, Py_None);
-       Py_DECREF(v);
-       Py_DECREF(w);
-       return res;
-}
-
 static PyObject *
 builtin_pow(self, args)
        PyObject *self;
        PyObject *args;
 {
-       PyObject *v, *w, *z = Py_None, *res;
-       PyObject *v1, *z1, *w2, *z2;
+       PyObject *v, *w, *z = Py_None;
 
        if (!PyArg_ParseTuple(args, "OO|O:pow", &v, &w, &z))
                return NULL;
-       if (z == Py_None)
-               return do_pow(v, w);
-       /* XXX The ternary version doesn't do class instance coercions */
-       if (PyInstance_Check(v))
-               return v->ob_type->tp_as_number->nb_power(v, w, z);
-       if (v->ob_type->tp_as_number == NULL ||
-           z->ob_type->tp_as_number == NULL ||
-           w->ob_type->tp_as_number == NULL) {
-               PyErr_SetString(PyExc_TypeError,
-                               "pow() requires numeric arguments");
-               return NULL;
-       }
-       if (PyNumber_Coerce(&v, &w) != 0)
-               return NULL;
-       res = NULL;
-       v1 = v;
-       z1 = z;
-       if (PyNumber_Coerce(&v1, &z1) != 0)
-               goto error2;
-       w2 = w;
-       z2 = z1;
-       if (PyNumber_Coerce(&w2, &z2) != 0)
-               goto error1;
-       res = (*v1->ob_type->tp_as_number->nb_power)(v1, w2, z2);
-       Py_DECREF(w2);
-       Py_DECREF(z2);
- error1:
-       Py_DECREF(v1);
-       Py_DECREF(z1);
- error2:
-       Py_DECREF(v);
-       Py_DECREF(w);
-       return res;
+       return PyNumber_Power(v, w, z);
 }
 
 static PyObject *
@@ -1401,7 +1247,8 @@ builtin_reduce(self, args)
        if (result != NULL)
                Py_INCREF(result);
 
-       if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
+       sqf = seq->ob_type->tp_as_sequence;
+       if (sqf == NULL || sqf->sq_item == NULL) {
                PyErr_SetString(PyExc_TypeError,
                    "2nd argument to reduce() must be a sequence object");
                return NULL;
@@ -1528,57 +1375,7 @@ builtin_tuple(self, args)
 
        if (!PyArg_ParseTuple(args, "O:tuple", &v))
                return NULL;
-       if (PyTuple_Check(v)) {
-               Py_INCREF(v);
-               return v;
-       }
-       if (PyList_Check(v))
-               return PyList_AsTuple(v);
-       if (PyString_Check(v)) {
-               int n = PyString_Size(v);
-               PyObject *t = PyTuple_New(n);
-               if (t != NULL) {
-                       int i;
-                       char *p = PyString_AsString(v);
-                       for (i = 0; i < n; i++) {
-                               PyObject *item =
-                                       PyString_FromStringAndSize(p+i, 1);
-                               if (item == NULL) {
-                                       Py_DECREF(t);
-                                       t = NULL;
-                                       break;
-                               }
-                               PyTuple_SetItem(t, i, item);
-                       }
-               }
-               return t;
-       }
-       /* Generic sequence object */
-       if ((sqf = v->ob_type->tp_as_sequence) != NULL) {
-               int n = (*sqf->sq_length)(v);
-               int i;
-               PyObject *t;
-               if (n < 0)
-                       return NULL;
-               t = PyTuple_New(n);
-               if (t == NULL)
-                       return NULL;
-               for (i = 0; i < n; i++) {
-                       PyObject *item = (*sqf->sq_item)(v, i);
-                       if (item == NULL) {
-                               Py_DECREF(t);
-                               t = NULL;
-                               break;
-                       }
-                       PyTuple_SetItem(t, i, item);
-               }
-               /* XXX Should support indefinite-length sequences */
-               return t;
-       }
-       /* None of the above */
-       PyErr_SetString(PyExc_TypeError,
-                       "tuple() argument must be a sequence");
-       return NULL;
+       return PySequence_Tuple(v);
 }
 
 static PyObject *
@@ -1815,6 +1612,7 @@ init_class_exc(dict)
        if (m == NULL ||
            (d = PyModule_GetDict(m)) == NULL)
        {
+               /* XXX Should use PySys_WriteStderr here */
                PyObject *f = PySys_GetObject("stderr");
                if (Py_VerboseFlag) {
                        PyFile_WriteString(
@@ -2093,117 +1891,3 @@ Fail_1:
        Py_DECREF(result);
        return NULL;
 }
-
-/* Copied with modifications from stropmodule.c: atoi,atof.atol */
-
-static PyObject *
-int_from_string(v)
-       PyObject *v;
-{
-       extern long PyOS_strtol Py_PROTO((const char *, char **, int));
-       char *s, *end;
-       long x;
-       char buffer[256]; /* For errors */
-
-       s = PyString_AS_STRING(v);
-       while (*s && isspace(Py_CHARMASK(*s)))
-               s++;
-       if (s[0] == '\0') {
-               PyErr_SetString(PyExc_ValueError, "empty string for int()");
-               return NULL;
-       }
-       errno = 0;
-       x = PyOS_strtol(s, &end, 10);
-       while (*end && isspace(Py_CHARMASK(*end)))
-               end++;
-       if (*end != '\0') {
-               sprintf(buffer, "invalid literal for int(): %.200s", s);
-               PyErr_SetString(PyExc_ValueError, buffer);
-               return NULL;
-       }
-       else if (end-s != PyString_GET_SIZE(v)) {
-               PyErr_SetString(PyExc_ValueError,
-                               "null byte in argument for int()");
-               return NULL;
-       }
-       else if (errno != 0) {
-               sprintf(buffer, "int() literal too large: %.200s", s);
-               PyErr_SetString(PyExc_ValueError, buffer);
-               return NULL;
-       }
-       return PyInt_FromLong(x);
-}
-
-static PyObject *
-long_from_string(v)
-       PyObject *v;
-{
-       char *s, *end;
-       PyObject *x;
-       char buffer[256]; /* For errors */
-
-       s = PyString_AS_STRING(v);
-       while (*s && isspace(Py_CHARMASK(*s)))
-               s++;
-       if (s[0] == '\0') {
-               PyErr_SetString(PyExc_ValueError, "empty string for long()");
-               return NULL;
-       }
-       x = PyLong_FromString(s, &end, 10);
-       if (x == NULL)
-               return NULL;
-       while (*end && isspace(Py_CHARMASK(*end)))
-               end++;
-       if (*end != '\0') {
-               sprintf(buffer, "invalid literal for long(): %.200s", s);
-               PyErr_SetString(PyExc_ValueError, buffer);
-               Py_DECREF(x);
-               return NULL;
-       }
-       else if (end-s != PyString_GET_SIZE(v)) {
-               PyErr_SetString(PyExc_ValueError,
-                               "null byte in argument for float()");
-               return NULL;
-       }
-       return x;
-}
-
-static PyObject *
-float_from_string(v)
-       PyObject *v;
-{
-       extern double strtod Py_PROTO((const char *, char **));
-       char *s, *end;
-       double x;
-       char buffer[256]; /* For errors */
-
-       s = PyString_AS_STRING(v);
-       while (*s && isspace(Py_CHARMASK(*s)))
-               s++;
-       if (s[0] == '\0') {
-               PyErr_SetString(PyExc_ValueError, "empty string for float()");
-               return NULL;
-       }
-       errno = 0;
-       PyFPE_START_PROTECT("float_from_string", return 0)
-       x = strtod(s, &end);
-       PyFPE_END_PROTECT(x)
-       while (*end && isspace(Py_CHARMASK(*end)))
-               end++;
-       if (*end != '\0') {
-               sprintf(buffer, "invalid literal for float(): %.200s", s);
-               PyErr_SetString(PyExc_ValueError, buffer);
-               return NULL;
-       }
-       else if (end-s != PyString_GET_SIZE(v)) {
-               PyErr_SetString(PyExc_ValueError,
-                               "null byte in argument for float()");
-               return NULL;
-       }
-       else if (errno != 0) {
-               sprintf(buffer, "float() literal too large: %.200s", s);
-               PyErr_SetString(PyExc_ValueError, buffer);
-               return NULL;
-       }
-       return PyFloat_FromDouble(x);
-}