summaryrefslogtreecommitdiff
path: root/Python/getargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/getargs.c')
-rw-r--r--Python/getargs.c523
1 files changed, 293 insertions, 230 deletions
diff --git a/Python/getargs.c b/Python/getargs.c
index 616c6eb107..952a662ecf 100644
--- a/Python/getargs.c
+++ b/Python/getargs.c
@@ -26,7 +26,9 @@ int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,
#ifdef HAVE_DECLSPEC_DLL
/* Export functions */
PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...);
-PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
+PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs,
+ const char *format, ...);
+PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
struct _PyArg_Parser *parser, ...);
PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);
PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *,
@@ -66,6 +68,8 @@ typedef struct {
#define STATIC_FREELIST_ENTRIES 8
/* Forward */
+static int vgetargs1_impl(PyObject *args, PyObject **stack, Py_ssize_t nargs,
+ const char *format, va_list *p_va, int flags);
static int vgetargs1(PyObject *, const char *, va_list *, int);
static void seterror(Py_ssize_t, const char *, int *, const char *, const char *);
static const char *convertitem(PyObject *, const char **, va_list *, int, int *,
@@ -74,7 +78,7 @@ static const char *converttuple(PyObject *, const char **, va_list *, int,
int *, char *, size_t, int, freelist_t *);
static const char *convertsimple(PyObject *, const char **, va_list *, int,
char *, size_t, freelist_t *);
-static Py_ssize_t convertbuffer(PyObject *, void **p, const char **);
+static Py_ssize_t convertbuffer(PyObject *, const void **p, const char **);
static int getbuffer(PyObject *, Py_buffer *, const char**);
static int vgetargskeywords(PyObject *, PyObject *,
@@ -138,6 +142,31 @@ _PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)
int
+_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, const char *format, ...)
+{
+ int retval;
+ va_list va;
+
+ va_start(va, format);
+ retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0);
+ va_end(va);
+ return retval;
+}
+
+int
+_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, const char *format, ...)
+{
+ int retval;
+ va_list va;
+
+ va_start(va, format);
+ retval = vgetargs1_impl(NULL, args, nargs, format, &va, FLAG_SIZE_T);
+ va_end(va);
+ return retval;
+}
+
+
+int
PyArg_VaParse(PyObject *args, const char *format, va_list va)
{
va_list lva;
@@ -220,7 +249,8 @@ cleanreturn(int retval, freelist_t *freelist)
static int
-vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
+vgetargs1_impl(PyObject *compat_args, PyObject **stack, Py_ssize_t nargs, const char *format,
+ va_list *p_va, int flags)
{
char msgbuf[256];
int levels[32];
@@ -231,17 +261,18 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
int level = 0;
int endfmt = 0;
const char *formatsave = format;
- Py_ssize_t i, len;
+ Py_ssize_t i;
const char *msg;
int compat = flags & FLAG_COMPAT;
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
freelist_t freelist;
+ assert(nargs == 0 || stack != NULL);
+
freelist.entries = static_entries;
freelist.first_available = 0;
freelist.entries_malloced = 0;
- assert(compat || (args != (PyObject*)NULL));
flags = flags & ~FLAG_COMPAT;
while (endfmt == 0) {
@@ -305,7 +336,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
if (compat) {
if (max == 0) {
- if (args == NULL)
+ if (compat_args == NULL)
return 1;
PyErr_Format(PyExc_TypeError,
"%.200s%s takes no arguments",
@@ -314,14 +345,14 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
return cleanreturn(0, &freelist);
}
else if (min == 1 && max == 1) {
- if (args == NULL) {
+ if (compat_args == NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s%s takes at least one argument",
fname==NULL ? "function" : fname,
fname==NULL ? "" : "()");
return cleanreturn(0, &freelist);
}
- msg = convertitem(args, &format, p_va, flags, levels,
+ msg = convertitem(compat_args, &format, p_va, flags, levels,
msgbuf, sizeof(msgbuf), &freelist);
if (msg == NULL)
return cleanreturn(1, &freelist);
@@ -335,34 +366,26 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
}
}
- if (!PyTuple_Check(args)) {
- PyErr_SetString(PyExc_SystemError,
- "new style getargs format but argument is not a tuple");
- return cleanreturn(0, &freelist);
- }
-
- len = PyTuple_GET_SIZE(args);
-
- if (len < min || max < len) {
+ if (nargs < min || max < nargs) {
if (message == NULL)
PyErr_Format(PyExc_TypeError,
"%.150s%s takes %s %d argument%s (%ld given)",
fname==NULL ? "function" : fname,
fname==NULL ? "" : "()",
min==max ? "exactly"
- : len < min ? "at least" : "at most",
- len < min ? min : max,
- (len < min ? min : max) == 1 ? "" : "s",
- Py_SAFE_DOWNCAST(len, Py_ssize_t, long));
+ : nargs < min ? "at least" : "at most",
+ nargs < min ? min : max,
+ (nargs < min ? min : max) == 1 ? "" : "s",
+ Py_SAFE_DOWNCAST(nargs, Py_ssize_t, long));
else
PyErr_SetString(PyExc_TypeError, message);
return cleanreturn(0, &freelist);
}
- for (i = 0; i < len; i++) {
+ for (i = 0; i < nargs; i++) {
if (*format == '|')
format++;
- msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va,
+ msg = convertitem(stack[i], &format, p_va,
flags, levels, msgbuf,
sizeof(msgbuf), &freelist);
if (msg) {
@@ -382,6 +405,31 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
return cleanreturn(1, &freelist);
}
+static int
+vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)
+{
+ PyObject **stack;
+ Py_ssize_t nargs;
+
+ if (!(flags & FLAG_COMPAT)) {
+ assert(args != NULL);
+
+ if (!PyTuple_Check(args)) {
+ PyErr_SetString(PyExc_SystemError,
+ "new style getargs format but argument is not a tuple");
+ return 0;
+ }
+
+ stack = &PyTuple_GET_ITEM(args, 0);
+ nargs = PyTuple_GET_SIZE(args);
+ }
+ else {
+ stack = NULL;
+ nargs = 0;
+ }
+
+ return vgetargs1_impl(args, stack, nargs, format, p_va, flags);
+}
static void
@@ -625,7 +673,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
const char *format = *p_format;
char c = *format++;
- char *sarg;
+ const char *sarg;
switch (c) {
@@ -897,7 +945,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
}
break;
}
- count = convertbuffer(arg, p, &buf);
+ count = convertbuffer(arg, (const void **)p, &buf);
if (count < 0)
return converterr(buf, arg, msgbuf, bufsize);
if (*format == '#') {
@@ -928,7 +976,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
if (sarg == NULL)
return converterr(CONV_UNICODE,
arg, msgbuf, bufsize);
- PyBuffer_FillInfo(p, arg, sarg, len, 1, 0);
+ PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0);
}
else { /* any bytes-like object */
const char *buf;
@@ -943,7 +991,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
format++;
} else if (*format == '#') { /* a string or read-only bytes-like object */
/* "s#" or "z#" */
- void **p = (void **)va_arg(*p_va, char **);
+ const void **p = (const void **)va_arg(*p_va, const char **);
FETCH_SIZE;
if (c == 'z' && arg == Py_None) {
@@ -970,7 +1018,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
format++;
} else {
/* "s" or "z" */
- char **p = va_arg(*p_va, char **);
+ const char **p = va_arg(*p_va, const char **);
Py_ssize_t len;
sarg = NULL;
@@ -1027,7 +1075,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
*p = PyUnicode_AsUnicodeAndSize(arg, &len);
if (*p == NULL)
RETURN_ERR_OCCURRED;
- if (Py_UNICODE_strlen(*p) != (size_t)len) {
+ if (wcslen(*p) != (size_t)len) {
PyErr_SetString(PyExc_ValueError, "embedded null character");
RETURN_ERR_OCCURRED;
}
@@ -1074,9 +1122,14 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
(PyBytes_Check(arg) || PyByteArray_Check(arg))) {
s = arg;
Py_INCREF(s);
- if (PyObject_AsCharBuffer(s, &ptr, &size) < 0)
- return converterr("(AsCharBuffer failed)",
- arg, msgbuf, bufsize);
+ if (PyBytes_Check(arg)) {
+ size = PyBytes_GET_SIZE(s);
+ ptr = PyBytes_AS_STRING(s);
+ }
+ else {
+ size = PyByteArray_GET_SIZE(s);
+ ptr = PyByteArray_AS_STRING(s);
+ }
}
else if (PyUnicode_Check(arg)) {
/* Encode object; use default error handling */
@@ -1300,7 +1353,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,
}
static Py_ssize_t
-convertbuffer(PyObject *arg, void **p, const char **errmsg)
+convertbuffer(PyObject *arg, const void **p, const char **errmsg)
{
PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer;
Py_ssize_t count;
@@ -1448,14 +1501,6 @@ _PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,
int retval;
va_list va;
- if ((args == NULL || !PyTuple_Check(args)) ||
- (keywords != NULL && !PyDict_Check(keywords)) ||
- parser == NULL)
- {
- PyErr_BadInternalCall();
- return 0;
- }
-
va_start(va, parser);
retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);
va_end(va);
@@ -1469,14 +1514,6 @@ _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
int retval;
va_list va;
- if ((args == NULL || !PyTuple_Check(args)) ||
- (keywords != NULL && !PyDict_Check(keywords)) ||
- parser == NULL)
- {
- PyErr_BadInternalCall();
- return 0;
- }
-
va_start(va, parser);
retval = vgetargskeywordsfast(args, keywords, parser, &va, FLAG_SIZE_T);
va_end(va);
@@ -1484,19 +1521,12 @@ _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
}
int
-_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
+_PyArg_ParseStackAndKeywords(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
struct _PyArg_Parser *parser, ...)
{
int retval;
va_list va;
- if ((kwnames != NULL && !PyTuple_Check(kwnames)) ||
- parser == NULL)
- {
- PyErr_BadInternalCall();
- return 0;
- }
-
va_start(va, parser);
retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0);
va_end(va);
@@ -1504,19 +1534,12 @@ _PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
}
int
-_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
+_PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,
struct _PyArg_Parser *parser, ...)
{
int retval;
va_list va;
- if ((kwnames != NULL && !PyTuple_Check(kwnames)) ||
- parser == NULL)
- {
- PyErr_BadInternalCall();
- return 0;
- }
-
va_start(va, parser);
retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, FLAG_SIZE_T);
va_end(va);
@@ -1531,14 +1554,6 @@ _PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,
int retval;
va_list lva;
- if ((args == NULL || !PyTuple_Check(args)) ||
- (keywords != NULL && !PyDict_Check(keywords)) ||
- parser == NULL)
- {
- PyErr_BadInternalCall();
- return 0;
- }
-
va_copy(lva, va);
retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0);
@@ -1553,14 +1568,6 @@ _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,
int retval;
va_list lva;
- if ((args == NULL || !PyTuple_Check(args)) ||
- (keywords != NULL && !PyDict_Check(keywords)) ||
- parser == NULL)
- {
- PyErr_BadInternalCall();
- return 0;
- }
-
va_copy(lva, va);
retval = vgetargskeywordsfast(args, keywords, parser, &lva, FLAG_SIZE_T);
@@ -1586,17 +1593,17 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs)
#define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':')
static int
-vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
+vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,
char **kwlist, va_list *p_va, int flags)
{
char msgbuf[512];
int levels[32];
- const char *fname, *msg, *custom_msg, *keyword;
+ const char *fname, *msg, *custom_msg;
int min = INT_MAX;
int max = INT_MAX;
int i, pos, len;
int skip = 0;
- Py_ssize_t nargs, nkeywords;
+ Py_ssize_t nargs, nkwargs;
PyObject *current_arg;
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
freelist_t freelist;
@@ -1606,7 +1613,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
freelist.entries_malloced = 0;
assert(args != NULL && PyTuple_Check(args));
- assert(keywords == NULL || PyDict_Check(keywords));
+ assert(kwargs == NULL || PyDict_Check(kwargs));
assert(format != NULL);
assert(kwlist != NULL);
assert(p_va != NULL);
@@ -1645,21 +1652,20 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
}
nargs = PyTuple_GET_SIZE(args);
- nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords);
- if (nargs + nkeywords > len) {
+ nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs);
+ if (nargs + nkwargs > len) {
PyErr_Format(PyExc_TypeError,
"%s%s takes at most %d argument%s (%zd given)",
(fname == NULL) ? "function" : fname,
(fname == NULL) ? "" : "()",
len,
(len == 1) ? "" : "s",
- nargs + nkeywords);
+ nargs + nkwargs);
return cleanreturn(0, &freelist);
}
/* convert tuple args and keyword args in same loop, using kwlist to drive process */
for (i = 0; i < len; i++) {
- keyword = kwlist[i];
if (*format == '|') {
if (min != INT_MAX) {
PyErr_SetString(PyExc_SystemError,
@@ -1713,26 +1719,17 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
return cleanreturn(0, &freelist);
}
if (!skip) {
- current_arg = NULL;
- if (nkeywords && i >= pos) {
- current_arg = PyDict_GetItemString(keywords, keyword);
- if (!current_arg && PyErr_Occurred()) {
- return cleanreturn(0, &freelist);
- }
+ if (i < nargs) {
+ current_arg = PyTuple_GET_ITEM(args, i);
}
- if (current_arg) {
- --nkeywords;
- if (i < nargs) {
- /* arg present in tuple and in dict */
- PyErr_Format(PyExc_TypeError,
- "Argument given by name ('%s') "
- "and position (%d)",
- keyword, i+1);
- return cleanreturn(0, &freelist);
- }
+ else if (nkwargs && i >= pos) {
+ current_arg = PyDict_GetItemString(kwargs, kwlist[i]);
+ if (current_arg)
+ --nkwargs;
+ }
+ else {
+ current_arg = NULL;
}
- else if (i < nargs)
- current_arg = PyTuple_GET_ITEM(args, i);
if (current_arg) {
msg = convertitem(current_arg, &format, p_va, flags,
@@ -1756,8 +1753,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
}
else {
PyErr_Format(PyExc_TypeError, "Required argument "
- "'%s' (pos %d) not found",
- keyword, i+1);
+ "'%s' (pos %d) not found",
+ kwlist[i], i+1);
return cleanreturn(0, &freelist);
}
}
@@ -1765,7 +1762,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
* fulfilled and no keyword args left, with no further
* validation. XXX Maybe skip this in debug build ?
*/
- if (!nkeywords && !skip) {
+ if (!nkwargs && !skip) {
return cleanreturn(1, &freelist);
}
}
@@ -1796,19 +1793,32 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,
return cleanreturn(0, &freelist);
}
- /* make sure there are no extraneous keyword arguments */
- if (nkeywords > 0) {
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- while (PyDict_Next(keywords, &pos, &key, &value)) {
+ if (nkwargs > 0) {
+ PyObject *key;
+ Py_ssize_t j;
+ /* make sure there are no arguments given by name and position */
+ for (i = pos; i < nargs; i++) {
+ current_arg = PyDict_GetItemString(kwargs, kwlist[i]);
+ if (current_arg) {
+ /* arg present in tuple and in dict */
+ PyErr_Format(PyExc_TypeError,
+ "Argument given by name ('%s') "
+ "and position (%d)",
+ kwlist[i], i+1);
+ return cleanreturn(0, &freelist);
+ }
+ }
+ /* make sure there are no extraneous keyword arguments */
+ j = 0;
+ while (PyDict_Next(kwargs, &j, &key, NULL)) {
int match = 0;
if (!PyUnicode_Check(key)) {
PyErr_SetString(PyExc_TypeError,
"keywords must be strings");
return cleanreturn(0, &freelist);
}
- for (i = 0; i < len; i++) {
- if (*kwlist[i] && _PyUnicode_EqualToASCIIString(key, kwlist[i])) {
+ for (i = pos; i < len; i++) {
+ if (_PyUnicode_EqualToASCIIString(key, kwlist[i])) {
match = 1;
break;
}
@@ -1956,10 +1966,13 @@ parser_clear(struct _PyArg_Parser *parser)
}
static PyObject*
-find_keyword(PyObject *kwnames, PyObject **kwstack, PyObject *key)
+find_keyword(PyObject *kwargs, PyObject *kwnames, PyObject **kwstack, PyObject *key)
{
Py_ssize_t i, nkwargs;
+ if (kwargs != NULL) {
+ return PyDict_GetItem(kwargs, key);
+ }
nkwargs = PyTuple_GET_SIZE(kwnames);
for (i=0; i < nkwargs; i++) {
PyObject *kwname = PyTuple_GET_ITEM(kwnames, i);
@@ -1971,7 +1984,7 @@ find_keyword(PyObject *kwnames, PyObject **kwstack, PyObject *key)
}
if (!PyUnicode_Check(kwname)) {
/* ignore non-string keyword keys:
- an error will be raised above */
+ an error will be raised below */
continue;
}
if (_PyUnicode_EQ(kwname, key)) {
@@ -1983,7 +1996,7 @@ find_keyword(PyObject *kwnames, PyObject **kwstack, PyObject *key)
static int
vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
- PyObject *keywords, PyObject *kwnames,
+ PyObject *kwargs, PyObject *kwnames,
struct _PyArg_Parser *parser,
va_list *p_va, int flags)
{
@@ -1994,7 +2007,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
const char *msg;
PyObject *keyword;
int i, pos, len;
- Py_ssize_t nkeywords;
+ Py_ssize_t nkwargs;
PyObject *current_arg;
freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];
freelist_t freelist;
@@ -2004,13 +2017,20 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
freelist.first_available = 0;
freelist.entries_malloced = 0;
- assert(keywords == NULL || PyDict_Check(keywords));
- assert(kwnames == NULL || PyTuple_Check(kwnames));
- assert((keywords != NULL || kwnames != NULL)
- || (keywords == NULL && kwnames == NULL));
- assert(parser != NULL);
+ assert(kwargs == NULL || PyDict_Check(kwargs));
+ assert(kwargs == NULL || kwnames == NULL);
assert(p_va != NULL);
+ if (parser == NULL) {
+ PyErr_BadInternalCall();
+ return 0;
+ }
+
+ if (kwnames != NULL && !PyTuple_Check(kwnames)) {
+ PyErr_BadInternalCall();
+ return 0;
+ }
+
if (!parser_init(parser)) {
return 0;
}
@@ -2028,24 +2048,24 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
freelist.entries_malloced = 1;
}
- if (keywords != NULL) {
- nkeywords = PyDict_Size(keywords);
+ if (kwargs != NULL) {
+ nkwargs = PyDict_GET_SIZE(kwargs);
}
else if (kwnames != NULL) {
- nkeywords = PyTuple_GET_SIZE(kwnames);
+ nkwargs = PyTuple_GET_SIZE(kwnames);
kwstack = args + nargs;
}
else {
- nkeywords = 0;
+ nkwargs = 0;
}
- if (nargs + nkeywords > len) {
+ if (nargs + nkwargs > len) {
PyErr_Format(PyExc_TypeError,
"%s%s takes at most %d argument%s (%zd given)",
(parser->fname == NULL) ? "function" : parser->fname,
(parser->fname == NULL) ? "" : "()",
len,
(len == 1) ? "" : "s",
- nargs + nkeywords);
+ nargs + nkwargs);
return cleanreturn(0, &freelist);
}
if (parser->max < nargs) {
@@ -2059,7 +2079,6 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
format = parser->format;
/* convert tuple args and keyword args in same loop, using kwtuple to drive process */
for (i = 0; i < len; i++) {
- keyword = (i >= pos) ? PyTuple_GET_ITEM(kwtuple, i - pos) : NULL;
if (*format == '|') {
format++;
}
@@ -2068,31 +2087,17 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
}
assert(!IS_END_OF_FORMAT(*format));
- current_arg = NULL;
- if (nkeywords && i >= pos) {
- if (keywords != NULL) {
- current_arg = PyDict_GetItem(keywords, keyword);
- if (!current_arg && PyErr_Occurred()) {
- return cleanreturn(0, &freelist);
- }
- }
- else {
- current_arg = find_keyword(kwnames, kwstack, keyword);
- }
+ if (i < nargs) {
+ current_arg = args[i];
}
- if (current_arg) {
- --nkeywords;
- if (i < nargs) {
- /* arg present in tuple and in dict */
- PyErr_Format(PyExc_TypeError,
- "Argument given by name ('%U') "
- "and position (%d)",
- keyword, i+1);
- return cleanreturn(0, &freelist);
- }
+ else if (nkwargs && i >= pos) {
+ keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
+ current_arg = find_keyword(kwargs, kwnames, kwstack, keyword);
+ if (current_arg)
+ --nkwargs;
}
- else if (i < nargs) {
- current_arg = args[i];
+ else {
+ current_arg = NULL;
}
if (current_arg) {
@@ -2108,13 +2113,15 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
if (i < parser->min) {
/* Less arguments than required */
if (i < pos) {
+ Py_ssize_t min = Py_MIN(pos, parser->min);
PyErr_Format(PyExc_TypeError,
"Function takes %s %d positional arguments"
" (%d given)",
- (Py_MIN(pos, parser->min) < parser->max) ? "at least" : "exactly",
- Py_MIN(pos, parser->min), nargs);
+ min < parser->max ? "at least" : "exactly",
+ min, nargs);
}
else {
+ keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
PyErr_Format(PyExc_TypeError, "Required argument "
"'%U' (pos %d) not found",
keyword, i+1);
@@ -2125,7 +2132,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
* fulfilled and no keyword args left, with no further
* validation. XXX Maybe skip this in debug build ?
*/
- if (!nkeywords) {
+ if (!nkwargs) {
return cleanreturn(1, &freelist);
}
@@ -2137,54 +2144,50 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,
assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$'));
- /* make sure there are no extraneous keyword arguments */
- if (nkeywords > 0) {
- if (keywords != NULL) {
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- while (PyDict_Next(keywords, &pos, &key, &value)) {
- int match;
- if (!PyUnicode_Check(key)) {
- PyErr_SetString(PyExc_TypeError,
- "keywords must be strings");
- return cleanreturn(0, &freelist);
- }
- match = PySequence_Contains(kwtuple, key);
- if (match <= 0) {
- if (!match) {
- PyErr_Format(PyExc_TypeError,
- "'%U' is an invalid keyword "
- "argument for this function",
- key);
- }
- return cleanreturn(0, &freelist);
- }
+ if (nkwargs > 0) {
+ Py_ssize_t j;
+ /* make sure there are no arguments given by name and position */
+ for (i = pos; i < nargs; i++) {
+ keyword = PyTuple_GET_ITEM(kwtuple, i - pos);
+ current_arg = find_keyword(kwargs, kwnames, kwstack, keyword);
+ if (current_arg) {
+ /* arg present in tuple and in dict */
+ PyErr_Format(PyExc_TypeError,
+ "Argument given by name ('%U') "
+ "and position (%d)",
+ keyword, i+1);
+ return cleanreturn(0, &freelist);
}
}
- else {
- Py_ssize_t j, nkwargs;
-
- nkwargs = PyTuple_GET_SIZE(kwnames);
- for (j=0; j < nkwargs; j++) {
- PyObject *key = PyTuple_GET_ITEM(kwnames, j);
- int match;
-
- if (!PyUnicode_Check(key)) {
- PyErr_SetString(PyExc_TypeError,
- "keywords must be strings");
- return cleanreturn(0, &freelist);
- }
+ /* make sure there are no extraneous keyword arguments */
+ j = 0;
+ while (1) {
+ int match;
+ if (kwargs != NULL) {
+ if (!PyDict_Next(kwargs, &j, &keyword, NULL))
+ break;
+ }
+ else {
+ if (j >= PyTuple_GET_SIZE(kwnames))
+ break;
+ keyword = PyTuple_GET_ITEM(kwnames, j);
+ j++;
+ }
- match = PySequence_Contains(kwtuple, key);
- if (match <= 0) {
- if (!match) {
- PyErr_Format(PyExc_TypeError,
- "'%U' is an invalid keyword "
- "argument for this function",
- key);
- }
- return cleanreturn(0, &freelist);
+ if (!PyUnicode_Check(keyword)) {
+ PyErr_SetString(PyExc_TypeError,
+ "keywords must be strings");
+ return cleanreturn(0, &freelist);
+ }
+ match = PySequence_Contains(kwtuple, keyword);
+ if (match <= 0) {
+ if (!match) {
+ PyErr_Format(PyExc_TypeError,
+ "'%U' is an invalid keyword "
+ "argument for this function",
+ keyword);
}
+ return cleanreturn(0, &freelist);
}
}
}
@@ -2199,7 +2202,13 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,
PyObject **stack;
Py_ssize_t nargs;
- assert(args != NULL && PyTuple_Check(args));
+ if (args == NULL
+ || !PyTuple_Check(args)
+ || (keywords != NULL && !PyDict_Check(keywords)))
+ {
+ PyErr_BadInternalCall();
+ return 0;
+ }
stack = &PyTuple_GET_ITEM(args, 0);
nargs = PyTuple_GET_SIZE(args);
@@ -2342,63 +2351,98 @@ err:
}
-int
-PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
+static int
+unpack_stack(PyObject **args, Py_ssize_t nargs, const char *name,
+ Py_ssize_t min, Py_ssize_t max, va_list vargs)
{
- Py_ssize_t i, l;
+ Py_ssize_t i;
PyObject **o;
- va_list vargs;
assert(min >= 0);
assert(min <= max);
- if (!PyTuple_Check(args)) {
- PyErr_SetString(PyExc_SystemError,
- "PyArg_UnpackTuple() argument list is not a tuple");
- return 0;
- }
- l = PyTuple_GET_SIZE(args);
- if (l < min) {
+
+ if (nargs < min) {
if (name != NULL)
PyErr_Format(
PyExc_TypeError,
"%s expected %s%zd arguments, got %zd",
- name, (min == max ? "" : "at least "), min, l);
+ name, (min == max ? "" : "at least "), min, nargs);
else
PyErr_Format(
PyExc_TypeError,
"unpacked tuple should have %s%zd elements,"
" but has %zd",
- (min == max ? "" : "at least "), min, l);
+ (min == max ? "" : "at least "), min, nargs);
return 0;
}
- if (l == 0)
+
+ if (nargs == 0) {
return 1;
- if (l > max) {
+ }
+
+ if (nargs > max) {
if (name != NULL)
PyErr_Format(
PyExc_TypeError,
"%s expected %s%zd arguments, got %zd",
- name, (min == max ? "" : "at most "), max, l);
+ name, (min == max ? "" : "at most "), max, nargs);
else
PyErr_Format(
PyExc_TypeError,
"unpacked tuple should have %s%zd elements,"
" but has %zd",
- (min == max ? "" : "at most "), max, l);
+ (min == max ? "" : "at most "), max, nargs);
return 0;
}
+ for (i = 0; i < nargs; i++) {
+ o = va_arg(vargs, PyObject **);
+ *o = args[i];
+ }
+ return 1;
+}
+
+int
+PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
+{
+ PyObject **stack;
+ Py_ssize_t nargs;
+ int retval;
+ va_list vargs;
+
+ if (!PyTuple_Check(args)) {
+ PyErr_SetString(PyExc_SystemError,
+ "PyArg_UnpackTuple() argument list is not a tuple");
+ return 0;
+ }
+ stack = &PyTuple_GET_ITEM(args, 0);
+ nargs = PyTuple_GET_SIZE(args);
+
#ifdef HAVE_STDARG_PROTOTYPES
va_start(vargs, max);
#else
va_start(vargs);
#endif
- for (i = 0; i < l; i++) {
- o = va_arg(vargs, PyObject **);
- *o = PyTuple_GET_ITEM(args, i);
- }
+ retval = unpack_stack(stack, nargs, name, min, max, vargs);
va_end(vargs);
- return 1;
+ return retval;
+}
+
+int
+_PyArg_UnpackStack(PyObject **args, Py_ssize_t nargs, const char *name,
+ Py_ssize_t min, Py_ssize_t max, ...)
+{
+ int retval;
+ va_list vargs;
+
+#ifdef HAVE_STDARG_PROTOTYPES
+ va_start(vargs, max);
+#else
+ va_start(vargs);
+#endif
+ retval = unpack_stack(args, nargs, name, min, max, vargs);
+ va_end(vargs);
+ return retval;
}
@@ -2408,16 +2452,35 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m
* not empty, returns 1 otherwise
*/
int
-_PyArg_NoKeywords(const char *funcname, PyObject *kw)
+_PyArg_NoKeywords(const char *funcname, PyObject *kwargs)
{
- if (kw == NULL)
+ if (kwargs == NULL) {
return 1;
- if (!PyDict_CheckExact(kw)) {
+ }
+ if (!PyDict_CheckExact(kwargs)) {
PyErr_BadInternalCall();
return 0;
}
- if (PyDict_Size(kw) == 0)
+ if (PyDict_GET_SIZE(kwargs) == 0) {
return 1;
+ }
+
+ PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments",
+ funcname);
+ return 0;
+}
+
+
+int
+_PyArg_NoStackKeywords(const char *funcname, PyObject *kwnames)
+{
+ if (kwnames == NULL) {
+ return 1;
+ }
+ assert(PyTuple_CheckExact(kwnames));
+ if (PyTuple_GET_SIZE(kwnames) == 0) {
+ return 1;
+ }
PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments",
funcname);