summaryrefslogtreecommitdiffstats
path: root/Python/bltinmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/bltinmodule.c')
-rw-r--r--Python/bltinmodule.c312
1 files changed, 211 insertions, 101 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index c8a8e83..d8e0d26 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -1,5 +1,5 @@
/***********************************************************
-Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
+Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
@@ -63,9 +63,52 @@ builtin_apply(self, args)
object *func, *arglist;
if (!getargs(args, "(OO)", &func, &arglist))
return NULL;
+ if (!is_tupleobject(arglist)) {
+ err_setstr(TypeError, "apply() 2nd argument must be tuple");
+ return NULL;
+ }
return call_object(func, arglist);
}
+static int
+callable(x)
+ object *x;
+{
+ if (x == NULL)
+ return 0;
+ if (x->ob_type->tp_call != NULL ||
+ is_funcobject(x) ||
+ is_instancemethodobject(x) ||
+ is_methodobject(x) ||
+ is_classobject(x))
+ return 1;
+ if (is_instanceobject(x)) {
+ object *call = getattr(x, "__call__");
+ if (call == NULL) {
+ err_clear();
+ return 0;
+ }
+ /* Could test recursively but don't, for fear of endless
+ recursion if some joker sets self.__call__ = self */
+ DECREF(call);
+ return 1;
+ }
+ return 0;
+}
+
+static object *
+builtin_callable(self, args)
+ object *self;
+ object *args;
+{
+ if (args == NULL) {
+ err_setstr(TypeError,
+ "callable requires exactly one argument");
+ return NULL;
+ }
+ return newintobject((long)callable(args));
+}
+
static object *
builtin_filter(self, args)
object *self;
@@ -107,12 +150,19 @@ builtin_filter(self, args)
goto Fail_2;
}
- for (i = j = 0; i < len; ++i) {
+ for (i = j = 0; ; ++i) {
object *item, *good;
int ok;
- if ((item = (*sqf->sq_item)(seq, i)) == NULL)
+ if ((item = (*sqf->sq_item)(seq, i)) == NULL) {
+ if (i < len)
+ goto Fail_1;
+ if (err_occurred() == IndexError) {
+ err_clear();
+ break;
+ }
goto Fail_1;
+ }
if (func == None) {
good = item;
@@ -131,13 +181,20 @@ builtin_filter(self, args)
DECREF(good);
if (ok) {
INCREF(item);
- if (setlistitem(result, j++, item) < 0)
- goto Fail_1;
+ if (j < len) {
+ if (setlistitem(result, j++, item) < 0)
+ goto Fail_1;
+ }
+ else {
+ j++;
+ if (addlistitem(result, item) < 0)
+ goto Fail_1;
+ }
}
}
- if (setlistslice(result, j, len, NULL) < 0)
+ if (j < len && setlistslice(result, j, len, NULL) < 0)
goto Fail_1;
return result;
@@ -453,7 +510,7 @@ builtin_map(self, args)
goto Fail_2;
}
- for (len = -1, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
+ for (len = 0, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
int curlen;
if ((sqp->seq = gettupleitem(args, i + 1)) == NULL)
@@ -480,55 +537,81 @@ builtin_map(self, args)
goto Fail_2;
/* XXX Special case map(None, single_list) could be more efficient */
- for (i = 0; i < len; ++i) {
- object *arglist, *item;
+ for (i = 0; ; ++i) {
+ object *arglist, *item, *value;
+ int any = 0;
- if ((arglist = newtupleobject(n)) == NULL)
- goto Fail_1;
+ if (func == None && n == 1)
+ arglist = NULL;
+ else {
+ if ((arglist = newtupleobject(n)) == NULL)
+ goto Fail_1;
+ }
for (j = 0, sqp = seqs; j < n; ++j, ++sqp) {
- if (i >= sqp->len) {
+ if (sqp->len < 0) {
INCREF(None);
item = None;
}
else {
item = (*sqp->sqf->sq_item)(sqp->seq, i);
- if (item == NULL)
- goto Fail_0;
+ if (item == NULL) {
+ if (i < sqp->len)
+ goto Fail_0;
+ if (err_occurred() == IndexError) {
+ err_clear();
+ INCREF(None);
+ item = None;
+ sqp->len = -1;
+ }
+ else {
+ goto Fail_0;
+ }
+ }
+ else
+ any = 1;
}
- if (settupleitem(arglist, j, item) < 0)
+ if (!arglist)
+ break;
+ if (settupleitem(arglist, j, item) < 0) {
+ DECREF(item);
goto Fail_0;
+ }
continue;
Fail_0:
- DECREF(arglist);
+ XDECREF(arglist);
goto Fail_1;
}
- if (func == None) {
- if (n == 1) { /* avoid creating singleton */
- INCREF(item); /* This is arglist[0] !!! */
- DECREF(arglist);
- if (setlistitem(result, i, item) < 0)
- goto Fail_1;
- }
- else {
- if (setlistitem(result, i, arglist) < 0)
- goto Fail_1;
- }
+ if (!arglist)
+ arglist = item;
+
+ if (!any) {
+ DECREF(arglist);
+ break;
}
+
+ if (func == None)
+ value = arglist;
else {
- object *value = call_object(func, arglist);
+ value = call_object(func, arglist);
DECREF(arglist);
if (value == NULL)
goto Fail_1;
- if (setlistitem((object *) result, i, value) < 0)
+ }
+ if (i >= len) {
+ if (addlistitem(result, value) < 0)
+ goto Fail_1;
+ }
+ else {
+ if (setlistitem(result, i, value) < 0)
goto Fail_1;
}
}
- if (seqs) DEL(seqs);
+ DEL(seqs);
return result;
Fail_1:
@@ -665,7 +748,7 @@ min_max(v, sign)
object *v;
int sign;
{
- int i, n, cmp;
+ int i;
object *w, *x;
sequence_methods *sq;
if (v == NULL) {
@@ -677,24 +760,30 @@ min_max(v, sign)
err_setstr(TypeError, "min() or max() of non-sequence");
return NULL;
}
- n = (*sq->sq_length)(v);
- if (n < 0)
- return NULL;
- if (n == 0) {
- err_setstr(ValueError, "min() or max() of empty sequence");
- return NULL;
- }
- w = (*sq->sq_item)(v, 0); /* Implies INCREF */
- for (i = 1; i < n; i++) {
+ w = NULL;
+ for (i = 0; ; i++) {
x = (*sq->sq_item)(v, i); /* Implies INCREF */
- cmp = cmpobject(x, w);
- if (cmp * sign > 0) {
- DECREF(w);
+ if (x == NULL) {
+ if (err_occurred() == IndexError) {
+ err_clear();
+ break;
+ }
+ XDECREF(w);
+ return NULL;
+ }
+ if (w == NULL)
w = x;
+ else {
+ if (cmpobject(x, w) * sign > 0) {
+ DECREF(w);
+ w = x;
+ }
+ else
+ DECREF(x);
}
- else
- DECREF(x);
}
+ if (w == NULL)
+ err_setstr(ValueError, "min() or max() of empty sequence");
return w;
}
@@ -735,10 +824,18 @@ builtin_open(self, args)
object *self;
object *args;
{
- char *name, *mode;
- if (!getargs(args, "(ss)", &name, &mode))
+ char *name;
+ char *mode = "r";
+ int bufsize = -1;
+ object *f;
+ if (!getargs(args, "s", &name) &&
+ (err_clear(), !getargs(args, "(ss)", &name, &mode)) &&
+ (err_clear(), !getargs(args, "(ssi)", &name, &mode, &bufsize)))
return NULL;
- return newfileobject(name, mode);
+ f = newfileobject(name, mode);
+ if (f != NULL)
+ setfilebufsize(f, bufsize);
+ return f;
}
static object *
@@ -920,25 +1017,15 @@ builtin_reduce(self, args)
{
object *seq, *func, *result;
sequence_methods *sqf;
- static char reduce_err[] = "reduce() requires 2 or 3 args";
register int i;
- int start = 0;
- int len;
-
- if (args == NULL || !is_tupleobject(args)) {
- err_setstr(TypeError, reduce_err);
- return NULL;
- }
- switch (gettuplesize(args)) {
- case 2:
- start = 1; /* fall through */
- case 3:
- func = gettupleitem(args, 0);
- seq = gettupleitem(args, 1);
- break;
- default:
- err_setstr(TypeError, reduce_err);
+ if (getargs(args, "(OO)", &func, &seq))
+ result = NULL;
+ else {
+ err_clear();
+ if (!getargs(args, "(OOO)", &func, &seq, &result))
+ return NULL;
+ INCREF(result);
}
if ((sqf = seq->ob_type->tp_as_sequence) == NULL) {
@@ -947,55 +1034,47 @@ builtin_reduce(self, args)
return NULL;
}
- if ((len = (*sqf->sq_length)(seq)) < 0)
- goto Fail_2;
-
- if (start == 1) {
- if (len == 0) {
- err_setstr(TypeError,
- "reduce of empty sequence with no initial value");
- goto Fail_2;
- }
-
- if ((result = (*sqf->sq_item)(seq, 0)) == NULL)
- goto Fail_2;
- }
- else {
- result = gettupleitem(args, 2);
- INCREF(result);
- }
-
if ((args = newtupleobject(2)) == NULL)
- goto Fail_1;
+ goto Fail;
- for (i = start; i < len; ++i) {
+ for (i = 0; ; ++i) {
object *op2;
if (args->ob_refcnt > 1) {
DECREF(args);
if ((args = newtupleobject(2)) == NULL)
- goto Fail_1;
+ goto Fail;
}
- if ((op2 = (*sqf->sq_item)(seq, i)) == NULL)
- goto Fail_2;
+ if ((op2 = (*sqf->sq_item)(seq, i)) == NULL) {
+ if (err_occurred() == IndexError) {
+ err_clear();
+ break;
+ }
+ goto Fail;
+ }
- settupleitem(args, 0, result);
- settupleitem(args, 1, op2);
- if ((result = call_object(func, args)) == NULL)
- goto Fail_0;
+ if (result == NULL)
+ result = op2;
+ else {
+ settupleitem(args, 0, result);
+ settupleitem(args, 1, op2);
+ if ((result = call_object(func, args)) == NULL)
+ goto Fail;
+ }
}
DECREF(args);
+ if (result == NULL)
+ err_setstr(TypeError,
+ "reduce of empty sequence with no initial value");
+
return result;
-Fail_0:
- DECREF(args);
- goto Fail_2;
-Fail_1:
- DECREF(result);
-Fail_2:
+Fail:
+ XDECREF(args);
+ XDECREF(result);
return NULL;
}
@@ -1073,9 +1152,31 @@ builtin_type(self, v)
return v;
}
+static object *
+builtin_vars(self, v)
+ object *self;
+ object *v;
+{
+ object *d;
+ if (v == NULL) {
+ d = getlocals();
+ INCREF(d);
+ }
+ else {
+ d = getattr(v, "__dict__");
+ if (d == NULL) {
+ err_setstr(TypeError,
+ "vars() argument must have __dict__ attribute");
+ return NULL;
+ }
+ }
+ return d;
+}
+
static struct methodlist builtin_methods[] = {
{"abs", builtin_abs},
{"apply", builtin_apply},
+ {"callable", builtin_callable},
{"chr", builtin_chr},
{"cmp", builtin_cmp},
{"coerce", builtin_coerce},
@@ -1111,6 +1212,7 @@ static struct methodlist builtin_methods[] = {
{"setattr", builtin_setattr},
{"str", builtin_str},
{"type", builtin_type},
+ {"vars", builtin_vars},
{"xrange", builtin_xrange},
{NULL, NULL},
};
@@ -1121,7 +1223,15 @@ object *
getbuiltin(name)
object *name;
{
- return dict2lookup(builtin_dict, name);
+ return mappinglookup(builtin_dict, name);
+}
+
+int
+setbuiltin(cname, value)
+ char *cname;
+ object *value;
+{
+ return dictinsert(builtin_dict, cname, value);
}
/* Predefined exceptions */
@@ -1291,8 +1401,8 @@ filterstring(func, strobj)
if (func == None) {
/* No character is ever false -- share input string */
- INCREF(result);
- return result;
+ INCREF(strobj);
+ return strobj;
}
if ((result = newsizedstringobject(NULL, len)) == NULL)
return NULL;