summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1997-03-31 17:15:43 (GMT)
committerGuido van Rossum <guido@python.org>1997-03-31 17:15:43 (GMT)
commitc6472e9ee161c3bbc003dbf8ce3f74ec8f700eb9 (patch)
tree66ec944c1e768be04dee20b62c292053a3e6843c
parentdddf7a6fb4f2486a5fbb06acafb3223424e95145 (diff)
downloadcpython-c6472e9ee161c3bbc003dbf8ce3f74ec8f700eb9.zip
cpython-c6472e9ee161c3bbc003dbf8ce3f74ec8f700eb9.tar.gz
cpython-c6472e9ee161c3bbc003dbf8ce3f74ec8f700eb9.tar.bz2
1. Add string conversions to int(), long(), float(). (Not to complex()!)
2. Fix two bugs in complex(): - Memory leak when using complex(classinstance) -- r was never DECREF'ed. - Conversion of the second argument, if not complex, was done using the type vector of the 1st.
-rw-r--r--Python/bltinmodule.c134
1 files changed, 127 insertions, 7 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 3d977f4..cee167c 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -49,6 +49,9 @@ PERFORMANCE OF THIS SOFTWARE.
/* Forward */
static object *filterstring PROTO((object *, object *));
static object *filtertuple PROTO((object *, object *));
+static object *int_from_string PROTO((object *));
+static object *long_from_string PROTO((object *));
+static object *float_from_string PROTO((object *));
static object *
builtin___import__(self, args)
@@ -300,14 +303,16 @@ builtin_complex(self, args)
object *r, *i, *tmp;
number_methods *nbr, *nbi;
Py_complex cr, ci;
+ int own_r = 0;
i = NULL;
if (!newgetargs(args, "O|O:complex", &r, &i))
return NULL;
if ((nbr = r->ob_type->tp_as_number) == NULL ||
- nbr->nb_float == NULL || (i != NULL &&
- ((nbi = i->ob_type->tp_as_number) == NULL ||
- nbi->nb_float == NULL))) {
+ nbr->nb_float == NULL ||
+ (i != NULL &&
+ ((nbi = i->ob_type->tp_as_number) == NULL ||
+ nbi->nb_float == NULL))) {
err_setstr(TypeError,
"complex() argument can't be converted to complex");
return NULL;
@@ -332,12 +337,18 @@ builtin_complex(self, args)
DECREF(args);
if (r == NULL)
return NULL;
+ own_r = 1;
}
}
- if (is_complexobject(r))
+ if (is_complexobject(r)) {
cr = ((complexobject*)r)->cval;
+ if (own_r)
+ DECREF(r);
+ }
else {
tmp = (*nbr->nb_float)(r);
+ if (own_r)
+ DECREF(r);
if (tmp == NULL)
return NULL;
cr.real = getfloatvalue(tmp);
@@ -351,7 +362,7 @@ builtin_complex(self, args)
else if (is_complexobject(i))
ci = ((complexobject*)i)->cval;
else {
- tmp = (*nbr->nb_float)(i);
+ tmp = (*nbi->nb_float)(i);
if (tmp == NULL)
return NULL;
ci.real = getfloatvalue(tmp);
@@ -533,6 +544,8 @@ builtin_float(self, args)
if (!newgetargs(args, "O:float", &v))
return NULL;
+ if (is_stringobject(v))
+ return float_from_string(v);
if ((nb = v->ob_type->tp_as_number) == NULL ||
nb->nb_float == NULL) {
err_setstr(TypeError,
@@ -863,6 +876,8 @@ builtin_int(self, args)
if (!newgetargs(args, "O:int", &v))
return NULL;
+ if (is_stringobject(v))
+ return int_from_string(v);
if ((nb = v->ob_type->tp_as_number) == NULL ||
nb->nb_int == NULL) {
err_setstr(TypeError,
@@ -981,6 +996,8 @@ builtin_long(self, args)
if (!newgetargs(args, "O:long", &v))
return NULL;
+ if (is_stringobject(v))
+ return long_from_string(v);
if ((nb = v->ob_type->tp_as_number) == NULL ||
nb->nb_long == NULL) {
err_setstr(TypeError,
@@ -1618,8 +1635,8 @@ getbuiltindict()
/* Predefined exceptions */
object *AccessError;
+object *PyExc_AssertionError;
object *AttributeError;
-object *ConflictError;
object *EOFError;
object *FloatingPointError;
object *IOError;
@@ -1652,8 +1669,8 @@ static void
initerrors()
{
AccessError = newstdexception("AccessError");
+ PyExc_AssertionError = newstdexception("AssertionError");
AttributeError = newstdexception("AttributeError");
- ConflictError = newstdexception("ConflictError");
EOFError = newstdexception("EOFError");
FloatingPointError = newstdexception("FloatingPointError");
IOError = newstdexception("IOError");
@@ -1797,3 +1814,106 @@ Fail_1:
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 */
+
+ if (!PyArg_Parse(v, "s", &s))
+ return NULL;
+ 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 (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 */
+
+ if (!PyArg_Parse(v, "s", &s))
+ return NULL;
+
+ 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;
+ }
+ 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 */
+
+ if (!PyArg_Parse(v, "s", &s))
+ return NULL;
+ 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 (errno != 0) {
+ sprintf(buffer, "float() literal too large: %.200s", s);
+ PyErr_SetString(PyExc_ValueError, buffer);
+ return NULL;
+ }
+ return PyFloat_FromDouble(x);
+}