diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/tools/python3/src/Python/getargs.c | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Python/getargs.c')
-rw-r--r-- | contrib/tools/python3/src/Python/getargs.c | 4832 |
1 files changed, 2416 insertions, 2416 deletions
diff --git a/contrib/tools/python3/src/Python/getargs.c b/contrib/tools/python3/src/Python/getargs.c index d4a531a5ef..cd512c96b7 100644 --- a/contrib/tools/python3/src/Python/getargs.c +++ b/contrib/tools/python3/src/Python/getargs.c @@ -1,619 +1,619 @@ - -/* New getargs implementation */ - -#include "Python.h" + +/* New getargs implementation */ + +#include "Python.h" #include "pycore_tupleobject.h" - -#include <ctype.h> -#include <float.h> - - -#ifdef __cplusplus -extern "C" { -#endif -int PyArg_Parse(PyObject *, const char *, ...); -int PyArg_ParseTuple(PyObject *, const char *, ...); -int PyArg_VaParse(PyObject *, const char *, va_list); - -int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, ...); -int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, - const char *, char **, va_list); - -int _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, - struct _PyArg_Parser *, ...); -int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *, - struct _PyArg_Parser *, va_list); - -#ifdef HAVE_DECLSPEC_DLL -/* Export functions */ -PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...); -PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject *const *args, Py_ssize_t nargs, - const char *format, ...); -PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject *const *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 *, - const char *, char **, ...); -PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); -PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list); -PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *, - const char *, char **, va_list); - -PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *, - struct _PyArg_Parser *, ...); -PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *, - struct _PyArg_Parser *, va_list); -#endif - -#define FLAG_COMPAT 1 -#define FLAG_SIZE_T 2 - -typedef int (*destr_t)(PyObject *, void *); - - -/* Keep track of "objects" that have been allocated or initialized and - which will need to be deallocated or cleaned up somehow if overall - parsing fails. -*/ -typedef struct { - void *item; - destr_t destructor; -} freelistentry_t; - -typedef struct { - freelistentry_t *entries; - int first_available; - int entries_malloced; -} freelist_t; - -#define STATIC_FREELIST_ENTRIES 8 - -/* Forward */ -static int vgetargs1_impl(PyObject *args, PyObject *const *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 *, - char *, size_t, freelist_t *); -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 *, const void **p, const char **); -static int getbuffer(PyObject *, Py_buffer *, const char**); - -static int vgetargskeywords(PyObject *, PyObject *, - const char *, char **, va_list *, int); -static int vgetargskeywordsfast(PyObject *, PyObject *, - struct _PyArg_Parser *, va_list *, int); -static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, - PyObject *keywords, PyObject *kwnames, - struct _PyArg_Parser *parser, - va_list *p_va, int flags); -static const char *skipitem(const char **, va_list *, int); - -int -PyArg_Parse(PyObject *args, const char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT); - va_end(va); - return retval; -} - + +#include <ctype.h> +#include <float.h> + + +#ifdef __cplusplus +extern "C" { +#endif +int PyArg_Parse(PyObject *, const char *, ...); +int PyArg_ParseTuple(PyObject *, const char *, ...); +int PyArg_VaParse(PyObject *, const char *, va_list); + +int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, + const char *, char **, ...); +int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, + const char *, char **, va_list); + +int _PyArg_ParseTupleAndKeywordsFast(PyObject *, PyObject *, + struct _PyArg_Parser *, ...); +int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *, + struct _PyArg_Parser *, va_list); + +#ifdef HAVE_DECLSPEC_DLL +/* Export functions */ +PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...); +PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject *const *args, Py_ssize_t nargs, + const char *format, ...); +PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject *const *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 *, + const char *, char **, ...); +PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); +PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, const char *, va_list); +PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *, + const char *, char **, va_list); + +PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *, + struct _PyArg_Parser *, ...); +PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *, PyObject *, + struct _PyArg_Parser *, va_list); +#endif + +#define FLAG_COMPAT 1 +#define FLAG_SIZE_T 2 + +typedef int (*destr_t)(PyObject *, void *); + + +/* Keep track of "objects" that have been allocated or initialized and + which will need to be deallocated or cleaned up somehow if overall + parsing fails. +*/ +typedef struct { + void *item; + destr_t destructor; +} freelistentry_t; + +typedef struct { + freelistentry_t *entries; + int first_available; + int entries_malloced; +} freelist_t; + +#define STATIC_FREELIST_ENTRIES 8 + +/* Forward */ +static int vgetargs1_impl(PyObject *args, PyObject *const *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 *, + char *, size_t, freelist_t *); +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 *, const void **p, const char **); +static int getbuffer(PyObject *, Py_buffer *, const char**); + +static int vgetargskeywords(PyObject *, PyObject *, + const char *, char **, va_list *, int); +static int vgetargskeywordsfast(PyObject *, PyObject *, + struct _PyArg_Parser *, va_list *, int); +static int vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, + PyObject *keywords, PyObject *kwnames, + struct _PyArg_Parser *parser, + va_list *p_va, int flags); +static const char *skipitem(const char **, va_list *, int); + +int +PyArg_Parse(PyObject *args, const char *format, ...) +{ + int retval; + va_list va; + + va_start(va, format); + retval = vgetargs1(args, format, &va, FLAG_COMPAT); + va_end(va); + return retval; +} + PyAPI_FUNC(int) -_PyArg_Parse_SizeT(PyObject *args, const char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); - va_end(va); - return retval; -} - - -int -PyArg_ParseTuple(PyObject *args, const char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, 0); - va_end(va); - return retval; -} - +_PyArg_Parse_SizeT(PyObject *args, const char *format, ...) +{ + int retval; + va_list va; + + va_start(va, format); + retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); + va_end(va); + return retval; +} + + +int +PyArg_ParseTuple(PyObject *args, const char *format, ...) +{ + int retval; + va_list va; + + va_start(va, format); + retval = vgetargs1(args, format, &va, 0); + va_end(va); + return retval; +} + PyAPI_FUNC(int) -_PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...) -{ - int retval; - va_list va; - - va_start(va, format); - retval = vgetargs1(args, format, &va, FLAG_SIZE_T); - va_end(va); - return retval; -} - - -int -_PyArg_ParseStack(PyObject *const *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; -} - +_PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...) +{ + int retval; + va_list va; + + va_start(va, format); + retval = vgetargs1(args, format, &va, FLAG_SIZE_T); + va_end(va); + return retval; +} + + +int +_PyArg_ParseStack(PyObject *const *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; +} + PyAPI_FUNC(int) -_PyArg_ParseStack_SizeT(PyObject *const *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; - int retval; - - va_copy(lva, va); - - retval = vgetargs1(args, format, &lva, 0); - va_end(lva); - return retval; -} - +_PyArg_ParseStack_SizeT(PyObject *const *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; + int retval; + + va_copy(lva, va); + + retval = vgetargs1(args, format, &lva, 0); + va_end(lva); + return retval; +} + PyAPI_FUNC(int) -_PyArg_VaParse_SizeT(PyObject *args, const char *format, va_list va) -{ - va_list lva; - int retval; - - va_copy(lva, va); - - retval = vgetargs1(args, format, &lva, FLAG_SIZE_T); - va_end(lva); - return retval; -} - - -/* Handle cleanup of allocated memory in case of exception */ - -static int -cleanup_ptr(PyObject *self, void *ptr) -{ - if (ptr) { - PyMem_FREE(ptr); - } - return 0; -} - -static int -cleanup_buffer(PyObject *self, void *ptr) -{ - Py_buffer *buf = (Py_buffer *)ptr; - if (buf) { - PyBuffer_Release(buf); - } - return 0; -} - -static int -addcleanup(void *ptr, freelist_t *freelist, destr_t destructor) -{ - int index; - - index = freelist->first_available; - freelist->first_available += 1; - - freelist->entries[index].item = ptr; - freelist->entries[index].destructor = destructor; - - return 0; -} - -static int -cleanreturn(int retval, freelist_t *freelist) -{ - int index; - - if (retval == 0) { - /* A failure occurred, therefore execute all of the cleanup - functions. - */ - for (index = 0; index < freelist->first_available; ++index) { - freelist->entries[index].destructor(NULL, - freelist->entries[index].item); - } - } - if (freelist->entries_malloced) - PyMem_FREE(freelist->entries); - return retval; -} - - -static int -vgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, const char *format, - va_list *p_va, int flags) -{ - char msgbuf[256]; - int levels[32]; - const char *fname = NULL; - const char *message = NULL; - int min = -1; - int max = 0; - int level = 0; - int endfmt = 0; - const char *formatsave = format; - 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; - - flags = flags & ~FLAG_COMPAT; - - while (endfmt == 0) { - int c = *format++; - switch (c) { - case '(': - if (level == 0) - max++; - level++; - if (level >= 30) - Py_FatalError("too many tuple nesting levels " - "in argument format string"); - break; - case ')': - if (level == 0) - Py_FatalError("excess ')' in getargs format"); - else - level--; - break; - case '\0': - endfmt = 1; - break; - case ':': - fname = format; - endfmt = 1; - break; - case ';': - message = format; - endfmt = 1; - break; - case '|': - if (level == 0) - min = max; - break; - default: - if (level == 0) { +_PyArg_VaParse_SizeT(PyObject *args, const char *format, va_list va) +{ + va_list lva; + int retval; + + va_copy(lva, va); + + retval = vgetargs1(args, format, &lva, FLAG_SIZE_T); + va_end(lva); + return retval; +} + + +/* Handle cleanup of allocated memory in case of exception */ + +static int +cleanup_ptr(PyObject *self, void *ptr) +{ + if (ptr) { + PyMem_FREE(ptr); + } + return 0; +} + +static int +cleanup_buffer(PyObject *self, void *ptr) +{ + Py_buffer *buf = (Py_buffer *)ptr; + if (buf) { + PyBuffer_Release(buf); + } + return 0; +} + +static int +addcleanup(void *ptr, freelist_t *freelist, destr_t destructor) +{ + int index; + + index = freelist->first_available; + freelist->first_available += 1; + + freelist->entries[index].item = ptr; + freelist->entries[index].destructor = destructor; + + return 0; +} + +static int +cleanreturn(int retval, freelist_t *freelist) +{ + int index; + + if (retval == 0) { + /* A failure occurred, therefore execute all of the cleanup + functions. + */ + for (index = 0; index < freelist->first_available; ++index) { + freelist->entries[index].destructor(NULL, + freelist->entries[index].item); + } + } + if (freelist->entries_malloced) + PyMem_FREE(freelist->entries); + return retval; +} + + +static int +vgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, const char *format, + va_list *p_va, int flags) +{ + char msgbuf[256]; + int levels[32]; + const char *fname = NULL; + const char *message = NULL; + int min = -1; + int max = 0; + int level = 0; + int endfmt = 0; + const char *formatsave = format; + 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; + + flags = flags & ~FLAG_COMPAT; + + while (endfmt == 0) { + int c = *format++; + switch (c) { + case '(': + if (level == 0) + max++; + level++; + if (level >= 30) + Py_FatalError("too many tuple nesting levels " + "in argument format string"); + break; + case ')': + if (level == 0) + Py_FatalError("excess ')' in getargs format"); + else + level--; + break; + case '\0': + endfmt = 1; + break; + case ':': + fname = format; + endfmt = 1; + break; + case ';': + message = format; + endfmt = 1; + break; + case '|': + if (level == 0) + min = max; + break; + default: + if (level == 0) { if (Py_ISALPHA(c)) - if (c != 'e') /* skip encoded */ - max++; - } - break; - } - } - - if (level != 0) - Py_FatalError(/* '(' */ "missing ')' in getargs format"); - - if (min < 0) - min = max; - - format = formatsave; - - if (max > STATIC_FREELIST_ENTRIES) { - freelist.entries = PyMem_NEW(freelistentry_t, max); - if (freelist.entries == NULL) { - PyErr_NoMemory(); - return 0; - } - freelist.entries_malloced = 1; - } - - if (compat) { - if (max == 0) { - if (compat_args == NULL) - return 1; - PyErr_Format(PyExc_TypeError, - "%.200s%s takes no arguments", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); - return cleanreturn(0, &freelist); - } - else if (min == 1 && max == 1) { - 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(compat_args, &format, p_va, flags, levels, - msgbuf, sizeof(msgbuf), &freelist); - if (msg == NULL) - return cleanreturn(1, &freelist); - seterror(levels[0], msg, levels+1, fname, message); - return cleanreturn(0, &freelist); - } - else { - PyErr_SetString(PyExc_SystemError, - "old style getargs format uses new features"); - return cleanreturn(0, &freelist); - } - } - - if (nargs < min || max < nargs) { - if (message == NULL) - PyErr_Format(PyExc_TypeError, + if (c != 'e') /* skip encoded */ + max++; + } + break; + } + } + + if (level != 0) + Py_FatalError(/* '(' */ "missing ')' in getargs format"); + + if (min < 0) + min = max; + + format = formatsave; + + if (max > STATIC_FREELIST_ENTRIES) { + freelist.entries = PyMem_NEW(freelistentry_t, max); + if (freelist.entries == NULL) { + PyErr_NoMemory(); + return 0; + } + freelist.entries_malloced = 1; + } + + if (compat) { + if (max == 0) { + if (compat_args == NULL) + return 1; + PyErr_Format(PyExc_TypeError, + "%.200s%s takes no arguments", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()"); + return cleanreturn(0, &freelist); + } + else if (min == 1 && max == 1) { + 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(compat_args, &format, p_va, flags, levels, + msgbuf, sizeof(msgbuf), &freelist); + if (msg == NULL) + return cleanreturn(1, &freelist); + seterror(levels[0], msg, levels+1, fname, message); + return cleanreturn(0, &freelist); + } + else { + PyErr_SetString(PyExc_SystemError, + "old style getargs format uses new features"); + return cleanreturn(0, &freelist); + } + } + + if (nargs < min || max < nargs) { + if (message == NULL) + PyErr_Format(PyExc_TypeError, "%.150s%s takes %s %d argument%s (%zd given)", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()", - min==max ? "exactly" - : nargs < min ? "at least" : "at most", - nargs < min ? min : max, - (nargs < min ? min : max) == 1 ? "" : "s", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()", + min==max ? "exactly" + : nargs < min ? "at least" : "at most", + nargs < min ? min : max, + (nargs < min ? min : max) == 1 ? "" : "s", nargs); - else - PyErr_SetString(PyExc_TypeError, message); - return cleanreturn(0, &freelist); - } - - for (i = 0; i < nargs; i++) { - if (*format == '|') - format++; - msg = convertitem(stack[i], &format, p_va, - flags, levels, msgbuf, - sizeof(msgbuf), &freelist); - if (msg) { - seterror(i+1, msg, levels, fname, message); - return cleanreturn(0, &freelist); - } - } - + else + PyErr_SetString(PyExc_TypeError, message); + return cleanreturn(0, &freelist); + } + + for (i = 0; i < nargs; i++) { + if (*format == '|') + format++; + msg = convertitem(stack[i], &format, p_va, + flags, levels, msgbuf, + sizeof(msgbuf), &freelist); + if (msg) { + seterror(i+1, msg, levels, fname, message); + return cleanreturn(0, &freelist); + } + } + if (*format != '\0' && !Py_ISALPHA(*format) && - *format != '(' && - *format != '|' && *format != ':' && *format != ';') { - PyErr_Format(PyExc_SystemError, - "bad format string: %.200s", formatsave); - return cleanreturn(0, &freelist); - } - - 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; - } - + *format != '(' && + *format != '|' && *format != ':' && *format != ';') { + PyErr_Format(PyExc_SystemError, + "bad format string: %.200s", formatsave); + return cleanreturn(0, &freelist); + } + + 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_ITEMS(args); - nargs = PyTuple_GET_SIZE(args); - } - else { - stack = NULL; - nargs = 0; - } - - return vgetargs1_impl(args, stack, nargs, format, p_va, flags); -} - - -static void -seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, - const char *message) -{ - char buf[512]; - int i; - char *p = buf; - - if (PyErr_Occurred()) - return; - else if (message == NULL) { - if (fname != NULL) { - PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname); - p += strlen(p); - } - if (iarg != 0) { - PyOS_snprintf(p, sizeof(buf) - (p - buf), - "argument %" PY_FORMAT_SIZE_T "d", iarg); - i = 0; - p += strlen(p); - while (i < 32 && levels[i] > 0 && (int)(p-buf) < 220) { - PyOS_snprintf(p, sizeof(buf) - (p - buf), - ", item %d", levels[i]-1); - p += strlen(p); - i++; - } - } - else { - PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument"); - p += strlen(p); - } - PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg); - message = buf; - } - if (msg[0] == '(') { - PyErr_SetString(PyExc_SystemError, message); - } - else { - PyErr_SetString(PyExc_TypeError, message); - } -} - - -/* Convert a tuple argument. - On entry, *p_format points to the character _after_ the opening '('. - On successful exit, *p_format points to the closing ')'. - If successful: - *p_format and *p_va are updated, - *levels and *msgbuf are untouched, - and NULL is returned. - If the argument is invalid: - *p_format is unchanged, - *p_va is undefined, - *levels is a 0-terminated list of item numbers, - *msgbuf contains an error message, whose format is: - "must be <typename1>, not <typename2>", where: - <typename1> is the name of the expected type, and - <typename2> is the name of the actual type, - and msgbuf is returned. -*/ - -static const char * -converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, int toplevel, - freelist_t *freelist) -{ - int level = 0; - int n = 0; - const char *format = *p_format; - int i; - Py_ssize_t len; - - for (;;) { - int c = *format++; - if (c == '(') { - if (level == 0) - n++; - level++; - } - else if (c == ')') { - if (level == 0) - break; - level--; - } - else if (c == ':' || c == ';' || c == '\0') - break; + nargs = PyTuple_GET_SIZE(args); + } + else { + stack = NULL; + nargs = 0; + } + + return vgetargs1_impl(args, stack, nargs, format, p_va, flags); +} + + +static void +seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, + const char *message) +{ + char buf[512]; + int i; + char *p = buf; + + if (PyErr_Occurred()) + return; + else if (message == NULL) { + if (fname != NULL) { + PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname); + p += strlen(p); + } + if (iarg != 0) { + PyOS_snprintf(p, sizeof(buf) - (p - buf), + "argument %" PY_FORMAT_SIZE_T "d", iarg); + i = 0; + p += strlen(p); + while (i < 32 && levels[i] > 0 && (int)(p-buf) < 220) { + PyOS_snprintf(p, sizeof(buf) - (p - buf), + ", item %d", levels[i]-1); + p += strlen(p); + i++; + } + } + else { + PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument"); + p += strlen(p); + } + PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg); + message = buf; + } + if (msg[0] == '(') { + PyErr_SetString(PyExc_SystemError, message); + } + else { + PyErr_SetString(PyExc_TypeError, message); + } +} + + +/* Convert a tuple argument. + On entry, *p_format points to the character _after_ the opening '('. + On successful exit, *p_format points to the closing ')'. + If successful: + *p_format and *p_va are updated, + *levels and *msgbuf are untouched, + and NULL is returned. + If the argument is invalid: + *p_format is unchanged, + *p_va is undefined, + *levels is a 0-terminated list of item numbers, + *msgbuf contains an error message, whose format is: + "must be <typename1>, not <typename2>", where: + <typename1> is the name of the expected type, and + <typename2> is the name of the actual type, + and msgbuf is returned. +*/ + +static const char * +converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, + int *levels, char *msgbuf, size_t bufsize, int toplevel, + freelist_t *freelist) +{ + int level = 0; + int n = 0; + const char *format = *p_format; + int i; + Py_ssize_t len; + + for (;;) { + int c = *format++; + if (c == '(') { + if (level == 0) + n++; + level++; + } + else if (c == ')') { + if (level == 0) + break; + level--; + } + else if (c == ':' || c == ';' || c == '\0') + break; else if (level == 0 && Py_ISALPHA(c)) - n++; - } - - if (!PySequence_Check(arg) || PyBytes_Check(arg)) { - levels[0] = 0; - PyOS_snprintf(msgbuf, bufsize, - toplevel ? "expected %d arguments, not %.50s" : - "must be %d-item sequence, not %.50s", - n, + n++; + } + + if (!PySequence_Check(arg) || PyBytes_Check(arg)) { + levels[0] = 0; + PyOS_snprintf(msgbuf, bufsize, + toplevel ? "expected %d arguments, not %.50s" : + "must be %d-item sequence, not %.50s", + n, arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); - return msgbuf; - } - - len = PySequence_Size(arg); - if (len != n) { - levels[0] = 0; - if (toplevel) { - PyOS_snprintf(msgbuf, bufsize, + return msgbuf; + } + + len = PySequence_Size(arg); + if (len != n) { + levels[0] = 0; + if (toplevel) { + PyOS_snprintf(msgbuf, bufsize, "expected %d argument%s, not %" PY_FORMAT_SIZE_T "d", n, n == 1 ? "" : "s", len); - } - else { - PyOS_snprintf(msgbuf, bufsize, - "must be sequence of length %d, " - "not %" PY_FORMAT_SIZE_T "d", - n, len); - } - return msgbuf; - } - - format = *p_format; - for (i = 0; i < n; i++) { - const char *msg; - PyObject *item; - item = PySequence_GetItem(arg, i); - if (item == NULL) { - PyErr_Clear(); - levels[0] = i+1; - levels[1] = 0; - strncpy(msgbuf, "is not retrievable", bufsize); - return msgbuf; - } - msg = convertitem(item, &format, p_va, flags, levels+1, - msgbuf, bufsize, freelist); - /* PySequence_GetItem calls tp->sq_item, which INCREFs */ - Py_XDECREF(item); - if (msg != NULL) { - levels[0] = i+1; - return msg; - } - } - - *p_format = format; - return NULL; -} - - -/* Convert a single item. */ - -static const char * -convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist) -{ - const char *msg; - const char *format = *p_format; - - if (*format == '(' /* ')' */) { - format++; - msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, - bufsize, 0, freelist); - if (msg == NULL) - format++; - } - else { - msg = convertsimple(arg, &format, p_va, flags, - msgbuf, bufsize, freelist); - if (msg != NULL) - levels[0] = 0; - } - if (msg == NULL) - *p_format = format; - return msg; -} - - - + } + else { + PyOS_snprintf(msgbuf, bufsize, + "must be sequence of length %d, " + "not %" PY_FORMAT_SIZE_T "d", + n, len); + } + return msgbuf; + } + + format = *p_format; + for (i = 0; i < n; i++) { + const char *msg; + PyObject *item; + item = PySequence_GetItem(arg, i); + if (item == NULL) { + PyErr_Clear(); + levels[0] = i+1; + levels[1] = 0; + strncpy(msgbuf, "is not retrievable", bufsize); + return msgbuf; + } + msg = convertitem(item, &format, p_va, flags, levels+1, + msgbuf, bufsize, freelist); + /* PySequence_GetItem calls tp->sq_item, which INCREFs */ + Py_XDECREF(item); + if (msg != NULL) { + levels[0] = i+1; + return msg; + } + } + + *p_format = format; + return NULL; +} + + +/* Convert a single item. */ + +static const char * +convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, + int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist) +{ + const char *msg; + const char *format = *p_format; + + if (*format == '(' /* ')' */) { + format++; + msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, + bufsize, 0, freelist); + if (msg == NULL) + format++; + } + else { + msg = convertsimple(arg, &format, p_va, flags, + msgbuf, bufsize, freelist); + if (msg != NULL) + levels[0] = 0; + } + if (msg == NULL) + *p_format = format; + return msg; +} + + + /* Format an error message generated by convertsimple(). displayname must be UTF-8 encoded. */ - + void _PyArg_BadArgument(const char *fname, const char *displayname, const char *expected, PyObject *arg) @@ -624,57 +624,57 @@ _PyArg_BadArgument(const char *fname, const char *displayname, arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); } -static const char * -converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) -{ - assert(expected != NULL); - assert(arg != NULL); - if (expected[0] == '(') { - PyOS_snprintf(msgbuf, bufsize, - "%.100s", expected); - } - else { - PyOS_snprintf(msgbuf, bufsize, - "must be %.50s, not %.50s", expected, +static const char * +converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) +{ + assert(expected != NULL); + assert(arg != NULL); + if (expected[0] == '(') { + PyOS_snprintf(msgbuf, bufsize, + "%.100s", expected); + } + else { + PyOS_snprintf(msgbuf, bufsize, + "must be %.50s, not %.50s", expected, arg == Py_None ? "None" : Py_TYPE(arg)->tp_name); - } - return msgbuf; -} - -#define CONV_UNICODE "(unicode conversion error)" - -/* Explicitly check for float arguments when integers are expected. + } + return msgbuf; +} + +#define CONV_UNICODE "(unicode conversion error)" + +/* Explicitly check for float arguments when integers are expected. Return 1 for error, 0 if ok. XXX Should be removed after the end of the deprecation period in _PyLong_FromNbIndexOrNbInt. */ -static int -float_argument_error(PyObject *arg) -{ - if (PyFloat_Check(arg)) { - PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); - return 1; - } - else - return 0; -} - -/* Convert a non-tuple argument. Return NULL if conversion went OK, - or a string with a message describing the failure. The message is - formatted as "must be <desired type>, not <actual type>". - When failing, an exception may or may not have been raised. - Don't call if a tuple is expected. - - When you add new format codes, please don't forget poor skipitem() below. -*/ - -static const char * -convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, - char *msgbuf, size_t bufsize, freelist_t *freelist) -{ - /* For # codes */ -#define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\ - if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \ +static int +float_argument_error(PyObject *arg) +{ + if (PyFloat_Check(arg)) { + PyErr_SetString(PyExc_TypeError, + "integer argument expected, got float" ); + return 1; + } + else + return 0; +} + +/* Convert a non-tuple argument. Return NULL if conversion went OK, + or a string with a message describing the failure. The message is + formatted as "must be <desired type>, not <actual type>". + When failing, an exception may or may not have been raised. + Don't call if a tuple is expected. + + When you add new format codes, please don't forget poor skipitem() below. +*/ + +static const char * +convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, + char *msgbuf, size_t bufsize, freelist_t *freelist) +{ + /* For # codes */ +#define FETCH_SIZE int *q=NULL;Py_ssize_t *q2=NULL;\ + if (flags & FLAG_SIZE_T) q2=va_arg(*p_va, Py_ssize_t*); \ else { \ if (PyErr_WarnEx(PyExc_DeprecationWarning, \ "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { \ @@ -682,527 +682,527 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } \ q=va_arg(*p_va, int*); \ } -#define STORE_SIZE(s) \ - if (flags & FLAG_SIZE_T) \ - *q2=s; \ - else { \ - if (INT_MAX < s) { \ - PyErr_SetString(PyExc_OverflowError, \ - "size does not fit in an int"); \ - return converterr("", arg, msgbuf, bufsize); \ - } \ - *q = (int)s; \ - } -#define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) -#define RETURN_ERR_OCCURRED return msgbuf - - const char *format = *p_format; - char c = *format++; - const char *sarg; - - switch (c) { - - case 'b': { /* unsigned byte -- very short int */ - char *p = va_arg(*p_va, char *); - long ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else if (ival < 0) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); - RETURN_ERR_OCCURRED; - } - else if (ival > UCHAR_MAX) { - PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); - RETURN_ERR_OCCURRED; - } - else - *p = (unsigned char) ival; - break; - } - - case 'B': {/* byte sized bitfield - both signed and unsigned - values allowed */ - char *p = va_arg(*p_va, char *); - long ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = (unsigned char) ival; - break; - } - - case 'h': {/* signed short int */ - short *p = va_arg(*p_va, short *); - long ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else if (ival < SHRT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - RETURN_ERR_OCCURRED; - } - else if (ival > SHRT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - RETURN_ERR_OCCURRED; - } - else - *p = (short) ival; - break; - } - - case 'H': { /* short int sized bitfield, both signed and - unsigned allowed */ - unsigned short *p = va_arg(*p_va, unsigned short *); - long ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsUnsignedLongMask(arg); - if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = (unsigned short) ival; - break; - } - - case 'i': {/* signed int */ - int *p = va_arg(*p_va, int *); - long ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else if (ival > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is greater than maximum"); - RETURN_ERR_OCCURRED; - } - else if (ival < INT_MIN) { - PyErr_SetString(PyExc_OverflowError, - "signed integer is less than minimum"); - RETURN_ERR_OCCURRED; - } - else - *p = ival; - break; - } - - case 'I': { /* int sized bitfield, both signed and - unsigned allowed */ - unsigned int *p = va_arg(*p_va, unsigned int *); - unsigned int ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); - if (ival == (unsigned int)-1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = ival; - break; - } - - case 'n': /* Py_ssize_t */ - { - PyObject *iobj; - Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); - Py_ssize_t ival = -1; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - iobj = PyNumber_Index(arg); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } - if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - *p = ival; - break; - } - case 'l': {/* long int */ - long *p = va_arg(*p_va, long *); - long ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLong(arg); - if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = ival; - break; - } - - case 'k': { /* long sized bitfield */ - unsigned long *p = va_arg(*p_va, unsigned long *); - unsigned long ival; - if (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongMask(arg); - else - return converterr("int", arg, msgbuf, bufsize); - *p = ival; - break; - } - - case 'L': {/* long long */ - long long *p = va_arg( *p_va, long long * ); - long long ival; - if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLongLong(arg); - if (ival == (long long)-1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = ival; - break; - } - - case 'K': { /* long long sized bitfield */ - unsigned long long *p = va_arg(*p_va, unsigned long long *); - unsigned long long ival; - if (PyLong_Check(arg)) - ival = PyLong_AsUnsignedLongLongMask(arg); - else - return converterr("int", arg, msgbuf, bufsize); - *p = ival; - break; - } - - case 'f': {/* float */ - float *p = va_arg(*p_va, float *); - double dval = PyFloat_AsDouble(arg); +#define STORE_SIZE(s) \ + if (flags & FLAG_SIZE_T) \ + *q2=s; \ + else { \ + if (INT_MAX < s) { \ + PyErr_SetString(PyExc_OverflowError, \ + "size does not fit in an int"); \ + return converterr("", arg, msgbuf, bufsize); \ + } \ + *q = (int)s; \ + } +#define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) +#define RETURN_ERR_OCCURRED return msgbuf + + const char *format = *p_format; + char c = *format++; + const char *sarg; + + switch (c) { + + case 'b': { /* unsigned byte -- very short int */ + char *p = va_arg(*p_va, char *); + long ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else if (ival < 0) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is less than minimum"); + RETURN_ERR_OCCURRED; + } + else if (ival > UCHAR_MAX) { + PyErr_SetString(PyExc_OverflowError, + "unsigned byte integer is greater than maximum"); + RETURN_ERR_OCCURRED; + } + else + *p = (unsigned char) ival; + break; + } + + case 'B': {/* byte sized bitfield - both signed and unsigned + values allowed */ + char *p = va_arg(*p_va, char *); + long ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = PyLong_AsUnsignedLongMask(arg); + if (ival == -1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else + *p = (unsigned char) ival; + break; + } + + case 'h': {/* signed short int */ + short *p = va_arg(*p_va, short *); + long ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else if (ival < SHRT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is less than minimum"); + RETURN_ERR_OCCURRED; + } + else if (ival > SHRT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed short integer is greater than maximum"); + RETURN_ERR_OCCURRED; + } + else + *p = (short) ival; + break; + } + + case 'H': { /* short int sized bitfield, both signed and + unsigned allowed */ + unsigned short *p = va_arg(*p_va, unsigned short *); + long ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = PyLong_AsUnsignedLongMask(arg); + if (ival == -1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else + *p = (unsigned short) ival; + break; + } + + case 'i': {/* signed int */ + int *p = va_arg(*p_va, int *); + long ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else if (ival > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "signed integer is greater than maximum"); + RETURN_ERR_OCCURRED; + } + else if (ival < INT_MIN) { + PyErr_SetString(PyExc_OverflowError, + "signed integer is less than minimum"); + RETURN_ERR_OCCURRED; + } + else + *p = ival; + break; + } + + case 'I': { /* int sized bitfield, both signed and + unsigned allowed */ + unsigned int *p = va_arg(*p_va, unsigned int *); + unsigned int ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = (unsigned int)PyLong_AsUnsignedLongMask(arg); + if (ival == (unsigned int)-1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else + *p = ival; + break; + } + + case 'n': /* Py_ssize_t */ + { + PyObject *iobj; + Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); + Py_ssize_t ival = -1; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + iobj = PyNumber_Index(arg); + if (iobj != NULL) { + ival = PyLong_AsSsize_t(iobj); + Py_DECREF(iobj); + } + if (ival == -1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + *p = ival; + break; + } + case 'l': {/* long int */ + long *p = va_arg(*p_va, long *); + long ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = PyLong_AsLong(arg); + if (ival == -1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else + *p = ival; + break; + } + + case 'k': { /* long sized bitfield */ + unsigned long *p = va_arg(*p_va, unsigned long *); + unsigned long ival; + if (PyLong_Check(arg)) + ival = PyLong_AsUnsignedLongMask(arg); + else + return converterr("int", arg, msgbuf, bufsize); + *p = ival; + break; + } + + case 'L': {/* long long */ + long long *p = va_arg( *p_va, long long * ); + long long ival; + if (float_argument_error(arg)) + RETURN_ERR_OCCURRED; + ival = PyLong_AsLongLong(arg); + if (ival == (long long)-1 && PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else + *p = ival; + break; + } + + case 'K': { /* long long sized bitfield */ + unsigned long long *p = va_arg(*p_va, unsigned long long *); + unsigned long long ival; + if (PyLong_Check(arg)) + ival = PyLong_AsUnsignedLongLongMask(arg); + else + return converterr("int", arg, msgbuf, bufsize); + *p = ival; + break; + } + + case 'f': {/* float */ + float *p = va_arg(*p_va, float *); + double dval = PyFloat_AsDouble(arg); if (dval == -1.0 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = (float) dval; - break; - } - - case 'd': {/* double */ - double *p = va_arg(*p_va, double *); - double dval = PyFloat_AsDouble(arg); + RETURN_ERR_OCCURRED; + else + *p = (float) dval; + break; + } + + case 'd': {/* double */ + double *p = va_arg(*p_va, double *); + double dval = PyFloat_AsDouble(arg); if (dval == -1.0 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = dval; - break; - } - - case 'D': {/* complex double */ - Py_complex *p = va_arg(*p_va, Py_complex *); - Py_complex cval; - cval = PyComplex_AsCComplex(arg); - if (PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else - *p = cval; - break; - } - - case 'c': {/* char */ - char *p = va_arg(*p_va, char *); - if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) - *p = PyBytes_AS_STRING(arg)[0]; - else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) - *p = PyByteArray_AS_STRING(arg)[0]; - else - return converterr("a byte string of length 1", arg, msgbuf, bufsize); - break; - } - - case 'C': {/* unicode char */ - int *p = va_arg(*p_va, int *); - int kind; + RETURN_ERR_OCCURRED; + else + *p = dval; + break; + } + + case 'D': {/* complex double */ + Py_complex *p = va_arg(*p_va, Py_complex *); + Py_complex cval; + cval = PyComplex_AsCComplex(arg); + if (PyErr_Occurred()) + RETURN_ERR_OCCURRED; + else + *p = cval; + break; + } + + case 'c': {/* char */ + char *p = va_arg(*p_va, char *); + if (PyBytes_Check(arg) && PyBytes_Size(arg) == 1) + *p = PyBytes_AS_STRING(arg)[0]; + else if (PyByteArray_Check(arg) && PyByteArray_Size(arg) == 1) + *p = PyByteArray_AS_STRING(arg)[0]; + else + return converterr("a byte string of length 1", arg, msgbuf, bufsize); + break; + } + + case 'C': {/* unicode char */ + int *p = va_arg(*p_va, int *); + int kind; const void *data; - - if (!PyUnicode_Check(arg)) - return converterr("a unicode character", arg, msgbuf, bufsize); - - if (PyUnicode_READY(arg)) - RETURN_ERR_OCCURRED; - - if (PyUnicode_GET_LENGTH(arg) != 1) - return converterr("a unicode character", arg, msgbuf, bufsize); - - kind = PyUnicode_KIND(arg); - data = PyUnicode_DATA(arg); - *p = PyUnicode_READ(kind, data, 0); - break; - } - - case 'p': {/* boolean *p*redicate */ - int *p = va_arg(*p_va, int *); - int val = PyObject_IsTrue(arg); - if (val > 0) - *p = 1; - else if (val == 0) - *p = 0; - else - RETURN_ERR_OCCURRED; - break; - } - - /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all - need to be cleaned up! */ - - case 'y': {/* any bytes-like object */ - void **p = (void **)va_arg(*p_va, char **); - const char *buf; - Py_ssize_t count; - if (*format == '*') { - if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - format++; - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - break; - } - count = convertbuffer(arg, (const void **)p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - if (*format == '#') { - FETCH_SIZE; - STORE_SIZE(count); - format++; - } else { - if (strlen(*p) != (size_t)count) { - PyErr_SetString(PyExc_ValueError, "embedded null byte"); - RETURN_ERR_OCCURRED; - } - } - break; - } - - case 's': /* text string or bytes-like object */ - case 'z': /* text string, bytes-like object or None */ - { - if (*format == '*') { - /* "s*" or "z*" */ - Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - - if (c == 'z' && arg == Py_None) - PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); - else if (PyUnicode_Check(arg)) { - Py_ssize_t len; - sarg = PyUnicode_AsUTF8AndSize(arg, &len); - if (sarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0); - } - else { /* any bytes-like object */ - const char *buf; - if (getbuffer(arg, p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - format++; - } else if (*format == '#') { /* a string or read-only bytes-like object */ - /* "s#" or "z#" */ - const void **p = (const void **)va_arg(*p_va, const char **); - FETCH_SIZE; - - if (c == 'z' && arg == Py_None) { - *p = NULL; - STORE_SIZE(0); - } - else if (PyUnicode_Check(arg)) { - Py_ssize_t len; - sarg = PyUnicode_AsUTF8AndSize(arg, &len); - if (sarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - *p = sarg; - STORE_SIZE(len); - } - else { /* read-only bytes-like object */ - /* XXX Really? */ - const char *buf; - Py_ssize_t count = convertbuffer(arg, p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - STORE_SIZE(count); - } - format++; - } else { - /* "s" or "z" */ - const char **p = va_arg(*p_va, const char **); - Py_ssize_t len; - sarg = NULL; - - if (c == 'z' && arg == Py_None) - *p = NULL; - else if (PyUnicode_Check(arg)) { - sarg = PyUnicode_AsUTF8AndSize(arg, &len); - if (sarg == NULL) - return converterr(CONV_UNICODE, - arg, msgbuf, bufsize); - if (strlen(sarg) != (size_t)len) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - RETURN_ERR_OCCURRED; - } - *p = sarg; - } - else - return converterr(c == 'z' ? "str or None" : "str", - arg, msgbuf, bufsize); - } - break; - } - - case 'u': /* raw unicode buffer (Py_UNICODE *) */ - case 'Z': /* raw unicode buffer or None */ - { + + if (!PyUnicode_Check(arg)) + return converterr("a unicode character", arg, msgbuf, bufsize); + + if (PyUnicode_READY(arg)) + RETURN_ERR_OCCURRED; + + if (PyUnicode_GET_LENGTH(arg) != 1) + return converterr("a unicode character", arg, msgbuf, bufsize); + + kind = PyUnicode_KIND(arg); + data = PyUnicode_DATA(arg); + *p = PyUnicode_READ(kind, data, 0); + break; + } + + case 'p': {/* boolean *p*redicate */ + int *p = va_arg(*p_va, int *); + int val = PyObject_IsTrue(arg); + if (val > 0) + *p = 1; + else if (val == 0) + *p = 0; + else + RETURN_ERR_OCCURRED; + break; + } + + /* XXX WAAAAH! 's', 'y', 'z', 'u', 'Z', 'e', 'w' codes all + need to be cleaned up! */ + + case 'y': {/* any bytes-like object */ + void **p = (void **)va_arg(*p_va, char **); + const char *buf; + Py_ssize_t count; + if (*format == '*') { + if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + format++; + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + break; + } + count = convertbuffer(arg, (const void **)p, &buf); + if (count < 0) + return converterr(buf, arg, msgbuf, bufsize); + if (*format == '#') { + FETCH_SIZE; + STORE_SIZE(count); + format++; + } else { + if (strlen(*p) != (size_t)count) { + PyErr_SetString(PyExc_ValueError, "embedded null byte"); + RETURN_ERR_OCCURRED; + } + } + break; + } + + case 's': /* text string or bytes-like object */ + case 'z': /* text string, bytes-like object or None */ + { + if (*format == '*') { + /* "s*" or "z*" */ + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (c == 'z' && arg == Py_None) + PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); + else if (PyUnicode_Check(arg)) { + Py_ssize_t len; + sarg = PyUnicode_AsUTF8AndSize(arg, &len); + if (sarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0); + } + else { /* any bytes-like object */ + const char *buf; + if (getbuffer(arg, p, &buf) < 0) + return converterr(buf, arg, msgbuf, bufsize); + } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + format++; + } else if (*format == '#') { /* a string or read-only bytes-like object */ + /* "s#" or "z#" */ + const void **p = (const void **)va_arg(*p_va, const char **); + FETCH_SIZE; + + if (c == 'z' && arg == Py_None) { + *p = NULL; + STORE_SIZE(0); + } + else if (PyUnicode_Check(arg)) { + Py_ssize_t len; + sarg = PyUnicode_AsUTF8AndSize(arg, &len); + if (sarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = sarg; + STORE_SIZE(len); + } + else { /* read-only bytes-like object */ + /* XXX Really? */ + const char *buf; + Py_ssize_t count = convertbuffer(arg, p, &buf); + if (count < 0) + return converterr(buf, arg, msgbuf, bufsize); + STORE_SIZE(count); + } + format++; + } else { + /* "s" or "z" */ + const char **p = va_arg(*p_va, const char **); + Py_ssize_t len; + sarg = NULL; + + if (c == 'z' && arg == Py_None) + *p = NULL; + else if (PyUnicode_Check(arg)) { + sarg = PyUnicode_AsUTF8AndSize(arg, &len); + if (sarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + if (strlen(sarg) != (size_t)len) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + RETURN_ERR_OCCURRED; + } + *p = sarg; + } + else + return converterr(c == 'z' ? "str or None" : "str", + arg, msgbuf, bufsize); + } + break; + } + + case 'u': /* raw unicode buffer (Py_UNICODE *) */ + case 'Z': /* raw unicode buffer or None */ + { // TODO: Raise DeprecationWarning _Py_COMP_DIAG_PUSH _Py_COMP_DIAG_IGNORE_DEPR_DECLS - Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); - - if (*format == '#') { - /* "u#" or "Z#" */ - FETCH_SIZE; - - if (c == 'Z' && arg == Py_None) { - *p = NULL; - STORE_SIZE(0); - } - else if (PyUnicode_Check(arg)) { - Py_ssize_t len; - *p = PyUnicode_AsUnicodeAndSize(arg, &len); - if (*p == NULL) - RETURN_ERR_OCCURRED; - STORE_SIZE(len); - } - else - return converterr(c == 'Z' ? "str or None" : "str", - arg, msgbuf, bufsize); - format++; - } else { - /* "u" or "Z" */ - if (c == 'Z' && arg == Py_None) - *p = NULL; - else if (PyUnicode_Check(arg)) { - Py_ssize_t len; - *p = PyUnicode_AsUnicodeAndSize(arg, &len); - if (*p == NULL) - RETURN_ERR_OCCURRED; - if (wcslen(*p) != (size_t)len) { - PyErr_SetString(PyExc_ValueError, "embedded null character"); - RETURN_ERR_OCCURRED; - } - } else - return converterr(c == 'Z' ? "str or None" : "str", - arg, msgbuf, bufsize); - } - break; + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + + if (*format == '#') { + /* "u#" or "Z#" */ + FETCH_SIZE; + + if (c == 'Z' && arg == Py_None) { + *p = NULL; + STORE_SIZE(0); + } + else if (PyUnicode_Check(arg)) { + Py_ssize_t len; + *p = PyUnicode_AsUnicodeAndSize(arg, &len); + if (*p == NULL) + RETURN_ERR_OCCURRED; + STORE_SIZE(len); + } + else + return converterr(c == 'Z' ? "str or None" : "str", + arg, msgbuf, bufsize); + format++; + } else { + /* "u" or "Z" */ + if (c == 'Z' && arg == Py_None) + *p = NULL; + else if (PyUnicode_Check(arg)) { + Py_ssize_t len; + *p = PyUnicode_AsUnicodeAndSize(arg, &len); + if (*p == NULL) + RETURN_ERR_OCCURRED; + if (wcslen(*p) != (size_t)len) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); + RETURN_ERR_OCCURRED; + } + } else + return converterr(c == 'Z' ? "str or None" : "str", + arg, msgbuf, bufsize); + } + break; _Py_COMP_DIAG_POP - } - - case 'e': {/* encoded string */ - char **buffer; - const char *encoding; - PyObject *s; - int recode_strings; - Py_ssize_t size; - const char *ptr; - - /* Get 'e' parameter: the encoding name */ - encoding = (const char *)va_arg(*p_va, const char *); - if (encoding == NULL) - encoding = PyUnicode_GetDefaultEncoding(); - - /* Get output buffer parameter: - 's' (recode all objects via Unicode) or - 't' (only recode non-string objects) - */ - if (*format == 's') - recode_strings = 1; - else if (*format == 't') - recode_strings = 0; - else - return converterr( - "(unknown parser marker combination)", - arg, msgbuf, bufsize); - buffer = (char **)va_arg(*p_va, char **); - format++; - if (buffer == NULL) - return converterr("(buffer is NULL)", - arg, msgbuf, bufsize); - - /* Encode object */ - if (!recode_strings && - (PyBytes_Check(arg) || PyByteArray_Check(arg))) { - s = arg; - Py_INCREF(s); - 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 */ - s = PyUnicode_AsEncodedString(arg, - encoding, - NULL); - if (s == NULL) - return converterr("(encoding failed)", - arg, msgbuf, bufsize); - assert(PyBytes_Check(s)); - size = PyBytes_GET_SIZE(s); - ptr = PyBytes_AS_STRING(s); - if (ptr == NULL) - ptr = ""; - } - else { - return converterr( - recode_strings ? "str" : "str, bytes or bytearray", - arg, msgbuf, bufsize); - } - - /* Write output; output is guaranteed to be 0-terminated */ - if (*format == '#') { - /* Using buffer length parameter '#': - - - if *buffer is NULL, a new buffer of the - needed size is allocated and the data - copied into it; *buffer is updated to point - to the new buffer; the caller is - responsible for PyMem_Free()ing it after - usage - - - if *buffer is not NULL, the data is - copied to *buffer; *buffer_len has to be - set to the size of the buffer on input; - buffer overflow is signalled with an error; - buffer has to provide enough room for the - encoded string plus the trailing 0-byte - - - in both cases, *buffer_len is updated to - the size of the buffer /excluding/ the - trailing 0-byte - - */ + } + + case 'e': {/* encoded string */ + char **buffer; + const char *encoding; + PyObject *s; + int recode_strings; + Py_ssize_t size; + const char *ptr; + + /* Get 'e' parameter: the encoding name */ + encoding = (const char *)va_arg(*p_va, const char *); + if (encoding == NULL) + encoding = PyUnicode_GetDefaultEncoding(); + + /* Get output buffer parameter: + 's' (recode all objects via Unicode) or + 't' (only recode non-string objects) + */ + if (*format == 's') + recode_strings = 1; + else if (*format == 't') + recode_strings = 0; + else + return converterr( + "(unknown parser marker combination)", + arg, msgbuf, bufsize); + buffer = (char **)va_arg(*p_va, char **); + format++; + if (buffer == NULL) + return converterr("(buffer is NULL)", + arg, msgbuf, bufsize); + + /* Encode object */ + if (!recode_strings && + (PyBytes_Check(arg) || PyByteArray_Check(arg))) { + s = arg; + Py_INCREF(s); + 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 */ + s = PyUnicode_AsEncodedString(arg, + encoding, + NULL); + if (s == NULL) + return converterr("(encoding failed)", + arg, msgbuf, bufsize); + assert(PyBytes_Check(s)); + size = PyBytes_GET_SIZE(s); + ptr = PyBytes_AS_STRING(s); + if (ptr == NULL) + ptr = ""; + } + else { + return converterr( + recode_strings ? "str" : "str, bytes or bytearray", + arg, msgbuf, bufsize); + } + + /* Write output; output is guaranteed to be 0-terminated */ + if (*format == '#') { + /* Using buffer length parameter '#': + + - if *buffer is NULL, a new buffer of the + needed size is allocated and the data + copied into it; *buffer is updated to point + to the new buffer; the caller is + responsible for PyMem_Free()ing it after + usage + + - if *buffer is not NULL, the data is + copied to *buffer; *buffer_len has to be + set to the size of the buffer on input; + buffer overflow is signalled with an error; + buffer has to provide enough room for the + encoded string plus the trailing 0-byte + + - in both cases, *buffer_len is updated to + the size of the buffer /excluding/ the + trailing 0-byte + + */ int *q = NULL; Py_ssize_t *q2 = NULL; if (flags & FLAG_SIZE_T) { q2 = va_arg(*p_va, Py_ssize_t*); @@ -1216,38 +1216,38 @@ _Py_COMP_DIAG_POP } q = va_arg(*p_va, int*); } - - format++; - if (q == NULL && q2 == NULL) { - Py_DECREF(s); - return converterr( - "(buffer_len is NULL)", - arg, msgbuf, bufsize); - } - if (*buffer == NULL) { - *buffer = PyMem_NEW(char, size + 1); - if (*buffer == NULL) { - Py_DECREF(s); - PyErr_NoMemory(); - RETURN_ERR_OCCURRED; - } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { - Py_DECREF(s); - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - } else { - if (size + 1 > BUFFER_LEN) { - Py_DECREF(s); - PyErr_Format(PyExc_ValueError, - "encoded string too long " - "(%zd, maximum length %zd)", - (Py_ssize_t)size, (Py_ssize_t)(BUFFER_LEN-1)); - RETURN_ERR_OCCURRED; - } - } - memcpy(*buffer, ptr, size+1); + + format++; + if (q == NULL && q2 == NULL) { + Py_DECREF(s); + return converterr( + "(buffer_len is NULL)", + arg, msgbuf, bufsize); + } + if (*buffer == NULL) { + *buffer = PyMem_NEW(char, size + 1); + if (*buffer == NULL) { + Py_DECREF(s); + PyErr_NoMemory(); + RETURN_ERR_OCCURRED; + } + if (addcleanup(*buffer, freelist, cleanup_ptr)) { + Py_DECREF(s); + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + } else { + if (size + 1 > BUFFER_LEN) { + Py_DECREF(s); + PyErr_Format(PyExc_ValueError, + "encoded string too long " + "(%zd, maximum length %zd)", + (Py_ssize_t)size, (Py_ssize_t)(BUFFER_LEN-1)); + RETURN_ERR_OCCURRED; + } + } + memcpy(*buffer, ptr, size+1); if (flags & FLAG_SIZE_T) { *q2 = size; @@ -1261,699 +1261,699 @@ _Py_COMP_DIAG_POP } *q = (int)size; } - } else { - /* Using a 0-terminated buffer: - - - the encoded string has to be 0-terminated - for this variant to work; if it is not, an - error raised - - - a new buffer of the needed size is - allocated and the data copied into it; - *buffer is updated to point to the new - buffer; the caller is responsible for - PyMem_Free()ing it after usage - - */ - if ((Py_ssize_t)strlen(ptr) != size) { - Py_DECREF(s); - return converterr( - "encoded string without null bytes", - arg, msgbuf, bufsize); - } - *buffer = PyMem_NEW(char, size + 1); - if (*buffer == NULL) { - Py_DECREF(s); - PyErr_NoMemory(); - RETURN_ERR_OCCURRED; - } - if (addcleanup(*buffer, freelist, cleanup_ptr)) { - Py_DECREF(s); - return converterr("(cleanup problem)", - arg, msgbuf, bufsize); - } - memcpy(*buffer, ptr, size+1); - } - Py_DECREF(s); - break; - } - - case 'S': { /* PyBytes object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyBytes_Check(arg)) - *p = arg; - else - return converterr("bytes", arg, msgbuf, bufsize); - break; - } - - case 'Y': { /* PyByteArray object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyByteArray_Check(arg)) - *p = arg; - else - return converterr("bytearray", arg, msgbuf, bufsize); - break; - } - - case 'U': { /* PyUnicode object */ - PyObject **p = va_arg(*p_va, PyObject **); - if (PyUnicode_Check(arg)) { - if (PyUnicode_READY(arg) == -1) - RETURN_ERR_OCCURRED; - *p = arg; - } - else - return converterr("str", arg, msgbuf, bufsize); - break; - } - - case 'O': { /* object */ - PyTypeObject *type; - PyObject **p; - if (*format == '!') { - type = va_arg(*p_va, PyTypeObject*); - p = va_arg(*p_va, PyObject **); - format++; + } else { + /* Using a 0-terminated buffer: + + - the encoded string has to be 0-terminated + for this variant to work; if it is not, an + error raised + + - a new buffer of the needed size is + allocated and the data copied into it; + *buffer is updated to point to the new + buffer; the caller is responsible for + PyMem_Free()ing it after usage + + */ + if ((Py_ssize_t)strlen(ptr) != size) { + Py_DECREF(s); + return converterr( + "encoded string without null bytes", + arg, msgbuf, bufsize); + } + *buffer = PyMem_NEW(char, size + 1); + if (*buffer == NULL) { + Py_DECREF(s); + PyErr_NoMemory(); + RETURN_ERR_OCCURRED; + } + if (addcleanup(*buffer, freelist, cleanup_ptr)) { + Py_DECREF(s); + return converterr("(cleanup problem)", + arg, msgbuf, bufsize); + } + memcpy(*buffer, ptr, size+1); + } + Py_DECREF(s); + break; + } + + case 'S': { /* PyBytes object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyBytes_Check(arg)) + *p = arg; + else + return converterr("bytes", arg, msgbuf, bufsize); + break; + } + + case 'Y': { /* PyByteArray object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyByteArray_Check(arg)) + *p = arg; + else + return converterr("bytearray", arg, msgbuf, bufsize); + break; + } + + case 'U': { /* PyUnicode object */ + PyObject **p = va_arg(*p_va, PyObject **); + if (PyUnicode_Check(arg)) { + if (PyUnicode_READY(arg) == -1) + RETURN_ERR_OCCURRED; + *p = arg; + } + else + return converterr("str", arg, msgbuf, bufsize); + break; + } + + case 'O': { /* object */ + PyTypeObject *type; + PyObject **p; + if (*format == '!') { + type = va_arg(*p_va, PyTypeObject*); + p = va_arg(*p_va, PyObject **); + format++; if (PyType_IsSubtype(Py_TYPE(arg), type)) - *p = arg; - else - return converterr(type->tp_name, arg, msgbuf, bufsize); - - } - else if (*format == '&') { - typedef int (*converter)(PyObject *, void *); - converter convert = va_arg(*p_va, converter); - void *addr = va_arg(*p_va, void *); - int res; - format++; - if (! (res = (*convert)(arg, addr))) - return converterr("(unspecified)", - arg, msgbuf, bufsize); - if (res == Py_CLEANUP_SUPPORTED && - addcleanup(addr, freelist, convert) == -1) - return converterr("(cleanup problem)", - arg, msgbuf, bufsize); - } - else { - p = va_arg(*p_va, PyObject **); - *p = arg; - } - break; - } - - - case 'w': { /* "w*": memory buffer, read-write access */ - void **p = va_arg(*p_va, void **); - - if (*format != '*') - return converterr( - "(invalid use of 'w' format character)", - arg, msgbuf, bufsize); - format++; - - /* Caller is interested in Py_buffer, and the object - supports it directly. */ - if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { - PyErr_Clear(); - return converterr("read-write bytes-like object", - arg, msgbuf, bufsize); - } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { - PyBuffer_Release((Py_buffer*)p); - return converterr("contiguous buffer", arg, msgbuf, bufsize); - } - if (addcleanup(p, freelist, cleanup_buffer)) { - return converterr( - "(cleanup problem)", - arg, msgbuf, bufsize); - } - break; - } - - default: - return converterr("(impossible<bad format char>)", arg, msgbuf, bufsize); - - } - - *p_format = format; - return NULL; - -#undef FETCH_SIZE -#undef STORE_SIZE -#undef BUFFER_LEN -#undef RETURN_ERR_OCCURRED -} - -static Py_ssize_t -convertbuffer(PyObject *arg, const void **p, const char **errmsg) -{ - PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; - Py_ssize_t count; - Py_buffer view; - - *errmsg = NULL; - *p = NULL; - if (pb != NULL && pb->bf_releasebuffer != NULL) { - *errmsg = "read-only bytes-like object"; - return -1; - } - - if (getbuffer(arg, &view, errmsg) < 0) - return -1; - count = view.len; - *p = view.buf; - PyBuffer_Release(&view); - return count; -} - -static int -getbuffer(PyObject *arg, Py_buffer *view, const char **errmsg) -{ - if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { - *errmsg = "bytes-like object"; - return -1; - } - if (!PyBuffer_IsContiguous(view, 'C')) { - PyBuffer_Release(view); - *errmsg = "contiguous buffer"; - return -1; - } - return 0; -} - -/* Support for keyword arguments donated by - Geoff Philbrick <philbric@delphi.hks.com> */ - -/* Return false (0) for error, else true. */ -int -PyArg_ParseTupleAndKeywords(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, ...) -{ - int retval; - va_list va; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_start(va, kwlist); - retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0); - va_end(va); - return retval; -} - + *p = arg; + else + return converterr(type->tp_name, arg, msgbuf, bufsize); + + } + else if (*format == '&') { + typedef int (*converter)(PyObject *, void *); + converter convert = va_arg(*p_va, converter); + void *addr = va_arg(*p_va, void *); + int res; + format++; + if (! (res = (*convert)(arg, addr))) + return converterr("(unspecified)", + arg, msgbuf, bufsize); + if (res == Py_CLEANUP_SUPPORTED && + addcleanup(addr, freelist, convert) == -1) + return converterr("(cleanup problem)", + arg, msgbuf, bufsize); + } + else { + p = va_arg(*p_va, PyObject **); + *p = arg; + } + break; + } + + + case 'w': { /* "w*": memory buffer, read-write access */ + void **p = va_arg(*p_va, void **); + + if (*format != '*') + return converterr( + "(invalid use of 'w' format character)", + arg, msgbuf, bufsize); + format++; + + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + if (PyObject_GetBuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write bytes-like object", + arg, msgbuf, bufsize); + } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { + PyBuffer_Release((Py_buffer*)p); + return converterr("contiguous buffer", arg, msgbuf, bufsize); + } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + break; + } + + default: + return converterr("(impossible<bad format char>)", arg, msgbuf, bufsize); + + } + + *p_format = format; + return NULL; + +#undef FETCH_SIZE +#undef STORE_SIZE +#undef BUFFER_LEN +#undef RETURN_ERR_OCCURRED +} + +static Py_ssize_t +convertbuffer(PyObject *arg, const void **p, const char **errmsg) +{ + PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; + Py_ssize_t count; + Py_buffer view; + + *errmsg = NULL; + *p = NULL; + if (pb != NULL && pb->bf_releasebuffer != NULL) { + *errmsg = "read-only bytes-like object"; + return -1; + } + + if (getbuffer(arg, &view, errmsg) < 0) + return -1; + count = view.len; + *p = view.buf; + PyBuffer_Release(&view); + return count; +} + +static int +getbuffer(PyObject *arg, Py_buffer *view, const char **errmsg) +{ + if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { + *errmsg = "bytes-like object"; + return -1; + } + if (!PyBuffer_IsContiguous(view, 'C')) { + PyBuffer_Release(view); + *errmsg = "contiguous buffer"; + return -1; + } + return 0; +} + +/* Support for keyword arguments donated by + Geoff Philbrick <philbric@delphi.hks.com> */ + +/* Return false (0) for error, else true. */ +int +PyArg_ParseTupleAndKeywords(PyObject *args, + PyObject *keywords, + const char *format, + char **kwlist, ...) +{ + int retval; + va_list va; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_start(va, kwlist); + retval = vgetargskeywords(args, keywords, format, kwlist, &va, 0); + va_end(va); + return retval; +} + PyAPI_FUNC(int) -_PyArg_ParseTupleAndKeywords_SizeT(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, ...) -{ - int retval; - va_list va; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_start(va, kwlist); - retval = vgetargskeywords(args, keywords, format, - kwlist, &va, FLAG_SIZE_T); - va_end(va); - return retval; -} - - -int -PyArg_VaParseTupleAndKeywords(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, va_list va) -{ - int retval; - va_list lva; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_copy(lva, va); - - retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); - va_end(lva); - return retval; -} - +_PyArg_ParseTupleAndKeywords_SizeT(PyObject *args, + PyObject *keywords, + const char *format, + char **kwlist, ...) +{ + int retval; + va_list va; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_start(va, kwlist); + retval = vgetargskeywords(args, keywords, format, + kwlist, &va, FLAG_SIZE_T); + va_end(va); + return retval; +} + + +int +PyArg_VaParseTupleAndKeywords(PyObject *args, + PyObject *keywords, + const char *format, + char **kwlist, va_list va) +{ + int retval; + va_list lva; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_copy(lva, va); + + retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); + va_end(lva); + return retval; +} + PyAPI_FUNC(int) -_PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, - PyObject *keywords, - const char *format, - char **kwlist, va_list va) -{ - int retval; - va_list lva; - - if ((args == NULL || !PyTuple_Check(args)) || - (keywords != NULL && !PyDict_Check(keywords)) || - format == NULL || - kwlist == NULL) - { - PyErr_BadInternalCall(); - return 0; - } - - va_copy(lva, va); - - retval = vgetargskeywords(args, keywords, format, - kwlist, &lva, FLAG_SIZE_T); - va_end(lva); - return retval; -} - +_PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, + PyObject *keywords, + const char *format, + char **kwlist, va_list va) +{ + int retval; + va_list lva; + + if ((args == NULL || !PyTuple_Check(args)) || + (keywords != NULL && !PyDict_Check(keywords)) || + format == NULL || + kwlist == NULL) + { + PyErr_BadInternalCall(); + return 0; + } + + va_copy(lva, va); + + retval = vgetargskeywords(args, keywords, format, + kwlist, &lva, FLAG_SIZE_T); + va_end(lva); + return retval; +} + PyAPI_FUNC(int) -_PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords, - struct _PyArg_Parser *parser, ...) -{ - int retval; - va_list va; - - va_start(va, parser); - retval = vgetargskeywordsfast(args, keywords, parser, &va, 0); - va_end(va); - return retval; -} - +_PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords, + struct _PyArg_Parser *parser, ...) +{ + int retval; + va_list va; + + va_start(va, parser); + retval = vgetargskeywordsfast(args, keywords, parser, &va, 0); + va_end(va); + return retval; +} + PyAPI_FUNC(int) -_PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords, - struct _PyArg_Parser *parser, ...) -{ - int retval; - va_list va; - - va_start(va, parser); - retval = vgetargskeywordsfast(args, keywords, parser, &va, FLAG_SIZE_T); - va_end(va); - return retval; -} - +_PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords, + struct _PyArg_Parser *parser, ...) +{ + int retval; + va_list va; + + va_start(va, parser); + retval = vgetargskeywordsfast(args, keywords, parser, &va, FLAG_SIZE_T); + va_end(va); + return retval; +} + PyAPI_FUNC(int) -_PyArg_ParseStackAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, - struct _PyArg_Parser *parser, ...) -{ - int retval; - va_list va; - - va_start(va, parser); - retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0); - va_end(va); - return retval; -} - +_PyArg_ParseStackAndKeywords(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, + struct _PyArg_Parser *parser, ...) +{ + int retval; + va_list va; + + va_start(va, parser); + retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0); + va_end(va); + return retval; +} + PyAPI_FUNC(int) -_PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, - struct _PyArg_Parser *parser, ...) -{ - int retval; - va_list va; - - va_start(va, parser); - retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, FLAG_SIZE_T); - va_end(va); - return retval; -} - - +_PyArg_ParseStackAndKeywords_SizeT(PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames, + struct _PyArg_Parser *parser, ...) +{ + int retval; + va_list va; + + va_start(va, parser); + retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, FLAG_SIZE_T); + va_end(va); + return retval; +} + + PyAPI_FUNC(int) -_PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords, - struct _PyArg_Parser *parser, va_list va) -{ - int retval; - va_list lva; - - va_copy(lva, va); - - retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0); - va_end(lva); - return retval; -} - +_PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords, + struct _PyArg_Parser *parser, va_list va) +{ + int retval; + va_list lva; + + va_copy(lva, va); + + retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0); + va_end(lva); + return retval; +} + PyAPI_FUNC(int) -_PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords, - struct _PyArg_Parser *parser, va_list va) -{ - int retval; - va_list lva; - - va_copy(lva, va); - - retval = vgetargskeywordsfast(args, keywords, parser, &lva, FLAG_SIZE_T); - va_end(lva); - return retval; -} - -int -PyArg_ValidateKeywordArguments(PyObject *kwargs) -{ - if (!PyDict_Check(kwargs)) { - PyErr_BadInternalCall(); - return 0; - } - if (!_PyDict_HasOnlyStringKeys(kwargs)) { - PyErr_SetString(PyExc_TypeError, - "keywords must be strings"); - return 0; - } - return 1; -} - -#define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') - -static int -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; - int min = INT_MAX; - int max = INT_MAX; - int i, pos, len; - int skip = 0; - Py_ssize_t nargs, nkwargs; - PyObject *current_arg; - freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; - freelist_t freelist; - - freelist.entries = static_entries; - freelist.first_available = 0; - freelist.entries_malloced = 0; - - assert(args != NULL && PyTuple_Check(args)); - assert(kwargs == NULL || PyDict_Check(kwargs)); - assert(format != NULL); - assert(kwlist != NULL); - assert(p_va != NULL); - - /* grab the function name or custom error msg first (mutually exclusive) */ - fname = strchr(format, ':'); - if (fname) { - fname++; - custom_msg = NULL; - } - else { - custom_msg = strchr(format,';'); - if (custom_msg) - custom_msg++; - } - - /* scan kwlist and count the number of positional-only parameters */ - for (pos = 0; kwlist[pos] && !*kwlist[pos]; pos++) { - } - /* scan kwlist and get greatest possible nbr of args */ - for (len = pos; kwlist[len]; len++) { - if (!*kwlist[len]) { - PyErr_SetString(PyExc_SystemError, - "Empty keyword parameter name"); - return cleanreturn(0, &freelist); - } - } - - if (len > STATIC_FREELIST_ENTRIES) { - freelist.entries = PyMem_NEW(freelistentry_t, len); - if (freelist.entries == NULL) { - PyErr_NoMemory(); - return 0; - } - freelist.entries_malloced = 1; - } - - nargs = PyTuple_GET_SIZE(args); - nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs); - if (nargs + nkwargs > len) { - /* Adding "keyword" (when nargs == 0) prevents producing wrong error - messages in some special cases (see bpo-31229). */ - PyErr_Format(PyExc_TypeError, - "%.200s%s takes at most %d %sargument%s (%zd given)", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()", - len, - (nargs == 0) ? "keyword " : "", - (len == 1) ? "" : "s", - 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++) { - if (*format == '|') { - if (min != INT_MAX) { - PyErr_SetString(PyExc_SystemError, - "Invalid format string (| specified twice)"); - return cleanreturn(0, &freelist); - } - - min = i; - format++; - - if (max != INT_MAX) { - PyErr_SetString(PyExc_SystemError, - "Invalid format string ($ before |)"); - return cleanreturn(0, &freelist); - } - } - if (*format == '$') { - if (max != INT_MAX) { - PyErr_SetString(PyExc_SystemError, - "Invalid format string ($ specified twice)"); - return cleanreturn(0, &freelist); - } - - max = i; - format++; - - if (max < pos) { - PyErr_SetString(PyExc_SystemError, - "Empty parameter name after $"); - return cleanreturn(0, &freelist); - } - if (skip) { - /* Now we know the minimal and the maximal numbers of - * positional arguments and can raise an exception with - * informative message (see below). */ - break; - } - if (max < nargs) { - if (max == 0) { - PyErr_Format(PyExc_TypeError, - "%.200s%s takes no positional arguments", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()"); - } - else { - PyErr_Format(PyExc_TypeError, +_PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords, + struct _PyArg_Parser *parser, va_list va) +{ + int retval; + va_list lva; + + va_copy(lva, va); + + retval = vgetargskeywordsfast(args, keywords, parser, &lva, FLAG_SIZE_T); + va_end(lva); + return retval; +} + +int +PyArg_ValidateKeywordArguments(PyObject *kwargs) +{ + if (!PyDict_Check(kwargs)) { + PyErr_BadInternalCall(); + return 0; + } + if (!_PyDict_HasOnlyStringKeys(kwargs)) { + PyErr_SetString(PyExc_TypeError, + "keywords must be strings"); + return 0; + } + return 1; +} + +#define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':') + +static int +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; + int min = INT_MAX; + int max = INT_MAX; + int i, pos, len; + int skip = 0; + Py_ssize_t nargs, nkwargs; + PyObject *current_arg; + freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; + freelist_t freelist; + + freelist.entries = static_entries; + freelist.first_available = 0; + freelist.entries_malloced = 0; + + assert(args != NULL && PyTuple_Check(args)); + assert(kwargs == NULL || PyDict_Check(kwargs)); + assert(format != NULL); + assert(kwlist != NULL); + assert(p_va != NULL); + + /* grab the function name or custom error msg first (mutually exclusive) */ + fname = strchr(format, ':'); + if (fname) { + fname++; + custom_msg = NULL; + } + else { + custom_msg = strchr(format,';'); + if (custom_msg) + custom_msg++; + } + + /* scan kwlist and count the number of positional-only parameters */ + for (pos = 0; kwlist[pos] && !*kwlist[pos]; pos++) { + } + /* scan kwlist and get greatest possible nbr of args */ + for (len = pos; kwlist[len]; len++) { + if (!*kwlist[len]) { + PyErr_SetString(PyExc_SystemError, + "Empty keyword parameter name"); + return cleanreturn(0, &freelist); + } + } + + if (len > STATIC_FREELIST_ENTRIES) { + freelist.entries = PyMem_NEW(freelistentry_t, len); + if (freelist.entries == NULL) { + PyErr_NoMemory(); + return 0; + } + freelist.entries_malloced = 1; + } + + nargs = PyTuple_GET_SIZE(args); + nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs); + if (nargs + nkwargs > len) { + /* Adding "keyword" (when nargs == 0) prevents producing wrong error + messages in some special cases (see bpo-31229). */ + PyErr_Format(PyExc_TypeError, + "%.200s%s takes at most %d %sargument%s (%zd given)", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()", + len, + (nargs == 0) ? "keyword " : "", + (len == 1) ? "" : "s", + 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++) { + if (*format == '|') { + if (min != INT_MAX) { + PyErr_SetString(PyExc_SystemError, + "Invalid format string (| specified twice)"); + return cleanreturn(0, &freelist); + } + + min = i; + format++; + + if (max != INT_MAX) { + PyErr_SetString(PyExc_SystemError, + "Invalid format string ($ before |)"); + return cleanreturn(0, &freelist); + } + } + if (*format == '$') { + if (max != INT_MAX) { + PyErr_SetString(PyExc_SystemError, + "Invalid format string ($ specified twice)"); + return cleanreturn(0, &freelist); + } + + max = i; + format++; + + if (max < pos) { + PyErr_SetString(PyExc_SystemError, + "Empty parameter name after $"); + return cleanreturn(0, &freelist); + } + if (skip) { + /* Now we know the minimal and the maximal numbers of + * positional arguments and can raise an exception with + * informative message (see below). */ + break; + } + if (max < nargs) { + if (max == 0) { + PyErr_Format(PyExc_TypeError, + "%.200s%s takes no positional arguments", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()"); + } + else { + PyErr_Format(PyExc_TypeError, "%.200s%s takes %s %d positional argument%s" " (%zd given)", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()", - (min != INT_MAX) ? "at most" : "exactly", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()", + (min != INT_MAX) ? "at most" : "exactly", max, max == 1 ? "" : "s", nargs); - } - return cleanreturn(0, &freelist); - } - } - if (IS_END_OF_FORMAT(*format)) { - PyErr_Format(PyExc_SystemError, - "More keyword list entries (%d) than " - "format specifiers (%d)", len, i); - return cleanreturn(0, &freelist); - } - if (!skip) { - if (i < nargs) { - current_arg = PyTuple_GET_ITEM(args, i); - } - else if (nkwargs && i >= pos) { + } + return cleanreturn(0, &freelist); + } + } + if (IS_END_OF_FORMAT(*format)) { + PyErr_Format(PyExc_SystemError, + "More keyword list entries (%d) than " + "format specifiers (%d)", len, i); + return cleanreturn(0, &freelist); + } + if (!skip) { + if (i < nargs) { + current_arg = PyTuple_GET_ITEM(args, i); + } + else if (nkwargs && i >= pos) { current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]); if (current_arg) { - --nkwargs; + --nkwargs; } else if (PyErr_Occurred()) { return cleanreturn(0, &freelist); } - } - else { - current_arg = NULL; - } - - if (current_arg) { - msg = convertitem(current_arg, &format, p_va, flags, - levels, msgbuf, sizeof(msgbuf), &freelist); - if (msg) { - seterror(i+1, msg, levels, fname, custom_msg); - return cleanreturn(0, &freelist); - } - continue; - } - - if (i < min) { - if (i < pos) { - assert (min == INT_MAX); - assert (max == INT_MAX); - skip = 1; - /* At that moment we still don't know the minimal and - * the maximal numbers of positional arguments. Raising - * an exception is deferred until we encounter | and $ - * or the end of the format. */ - } - else { - PyErr_Format(PyExc_TypeError, "%.200s%s missing required " - "argument '%s' (pos %d)", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()", - kwlist[i], i+1); - return cleanreturn(0, &freelist); - } - } - /* current code reports success when all required args - * fulfilled and no keyword args left, with no further - * validation. XXX Maybe skip this in debug build ? - */ - if (!nkwargs && !skip) { - return cleanreturn(1, &freelist); - } - } - - /* We are into optional args, skip through to any remaining - * keyword args */ - msg = skipitem(&format, p_va, flags); - if (msg) { - PyErr_Format(PyExc_SystemError, "%s: '%s'", msg, - format); - return cleanreturn(0, &freelist); - } - } - - if (skip) { - PyErr_Format(PyExc_TypeError, + } + else { + current_arg = NULL; + } + + if (current_arg) { + msg = convertitem(current_arg, &format, p_va, flags, + levels, msgbuf, sizeof(msgbuf), &freelist); + if (msg) { + seterror(i+1, msg, levels, fname, custom_msg); + return cleanreturn(0, &freelist); + } + continue; + } + + if (i < min) { + if (i < pos) { + assert (min == INT_MAX); + assert (max == INT_MAX); + skip = 1; + /* At that moment we still don't know the minimal and + * the maximal numbers of positional arguments. Raising + * an exception is deferred until we encounter | and $ + * or the end of the format. */ + } + else { + PyErr_Format(PyExc_TypeError, "%.200s%s missing required " + "argument '%s' (pos %d)", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()", + kwlist[i], i+1); + return cleanreturn(0, &freelist); + } + } + /* current code reports success when all required args + * fulfilled and no keyword args left, with no further + * validation. XXX Maybe skip this in debug build ? + */ + if (!nkwargs && !skip) { + return cleanreturn(1, &freelist); + } + } + + /* We are into optional args, skip through to any remaining + * keyword args */ + msg = skipitem(&format, p_va, flags); + if (msg) { + PyErr_Format(PyExc_SystemError, "%s: '%s'", msg, + format); + return cleanreturn(0, &freelist); + } + } + + if (skip) { + PyErr_Format(PyExc_TypeError, "%.200s%s takes %s %d positional argument%s" " (%zd given)", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()", - (Py_MIN(pos, min) < i) ? "at least" : "exactly", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()", + (Py_MIN(pos, min) < i) ? "at least" : "exactly", Py_MIN(pos, min), Py_MIN(pos, min) == 1 ? "" : "s", nargs); - return cleanreturn(0, &freelist); - } - - if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) { - PyErr_Format(PyExc_SystemError, - "more argument specifiers than keyword list entries " - "(remaining format:'%s')", format); - return cleanreturn(0, &freelist); - } - - 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++) { + return cleanreturn(0, &freelist); + } + + if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) { + PyErr_Format(PyExc_SystemError, + "more argument specifiers than keyword list entries " + "(remaining format:'%s')", format); + return cleanreturn(0, &freelist); + } + + 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_GetItemStringWithError(kwargs, kwlist[i]); - if (current_arg) { - /* arg present in tuple and in dict */ - PyErr_Format(PyExc_TypeError, - "argument for %.200s%s given by name ('%s') " - "and position (%d)", - (fname == NULL) ? "function" : fname, - (fname == NULL) ? "" : "()", - kwlist[i], i+1); - return cleanreturn(0, &freelist); - } + if (current_arg) { + /* arg present in tuple and in dict */ + PyErr_Format(PyExc_TypeError, + "argument for %.200s%s given by name ('%s') " + "and position (%d)", + (fname == NULL) ? "function" : fname, + (fname == NULL) ? "" : "()", + kwlist[i], i+1); + return cleanreturn(0, &freelist); + } else if (PyErr_Occurred()) { 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 = pos; i < len; i++) { - if (_PyUnicode_EqualToASCIIString(key, kwlist[i])) { - match = 1; - break; - } - } - if (!match) { - PyErr_Format(PyExc_TypeError, - "'%U' is an invalid keyword " - "argument for %.200s%s", - key, - (fname == NULL) ? "this function" : fname, - (fname == NULL) ? "" : "()"); - return cleanreturn(0, &freelist); - } - } - } - - return cleanreturn(1, &freelist); -} - - -/* List of static parsers. */ -static struct _PyArg_Parser *static_arg_parsers = NULL; - -static int -parser_init(struct _PyArg_Parser *parser) -{ - const char * const *keywords; - const char *format, *msg; - int i, len, min, max, nkw; - PyObject *kwtuple; - - assert(parser->keywords != NULL); - if (parser->kwtuple != NULL) { - return 1; - } - - keywords = parser->keywords; - /* scan keywords and count the number of positional-only parameters */ - for (i = 0; keywords[i] && !*keywords[i]; i++) { - } - parser->pos = i; - /* scan keywords and get greatest possible nbr of args */ - for (; keywords[i]; i++) { - if (!*keywords[i]) { - PyErr_SetString(PyExc_SystemError, - "Empty keyword parameter name"); - return 0; - } - } - len = i; - - format = parser->format; + } + /* 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 = pos; i < len; i++) { + if (_PyUnicode_EqualToASCIIString(key, kwlist[i])) { + match = 1; + break; + } + } + if (!match) { + PyErr_Format(PyExc_TypeError, + "'%U' is an invalid keyword " + "argument for %.200s%s", + key, + (fname == NULL) ? "this function" : fname, + (fname == NULL) ? "" : "()"); + return cleanreturn(0, &freelist); + } + } + } + + return cleanreturn(1, &freelist); +} + + +/* List of static parsers. */ +static struct _PyArg_Parser *static_arg_parsers = NULL; + +static int +parser_init(struct _PyArg_Parser *parser) +{ + const char * const *keywords; + const char *format, *msg; + int i, len, min, max, nkw; + PyObject *kwtuple; + + assert(parser->keywords != NULL); + if (parser->kwtuple != NULL) { + return 1; + } + + keywords = parser->keywords; + /* scan keywords and count the number of positional-only parameters */ + for (i = 0; keywords[i] && !*keywords[i]; i++) { + } + parser->pos = i; + /* scan keywords and get greatest possible nbr of args */ + for (; keywords[i]; i++) { + if (!*keywords[i]) { + PyErr_SetString(PyExc_SystemError, + "Empty keyword parameter name"); + return 0; + } + } + len = i; + + format = parser->format; if (format) { /* grab the function name or custom error msg first (mutually exclusive) */ parser->fname = strchr(parser->format, ':'); @@ -1982,7 +1982,7 @@ parser_init(struct _PyArg_Parser *parser) } min = i; format++; - } + } if (*format == '$') { if (max != INT_MAX) { PyErr_SetString(PyExc_SystemError, @@ -1996,200 +1996,200 @@ parser_init(struct _PyArg_Parser *parser) } max = i; format++; - } + } if (IS_END_OF_FORMAT(*format)) { PyErr_Format(PyExc_SystemError, "More keyword list entries (%d) than " "format specifiers (%d)", len, i); - return 0; - } + return 0; + } msg = skipitem(&format, NULL, 0); if (msg) { PyErr_Format(PyExc_SystemError, "%s: '%s'", msg, format); - return 0; - } - } + return 0; + } + } parser->min = Py_MIN(min, len); parser->max = Py_MIN(max, len); if (!IS_END_OF_FORMAT(*format) && (*format != '|') && (*format != '$')) { - PyErr_Format(PyExc_SystemError, + PyErr_Format(PyExc_SystemError, "more argument specifiers than keyword list entries " "(remaining format:'%s')", format); - return 0; - } - } - - nkw = len - parser->pos; - kwtuple = PyTuple_New(nkw); - if (kwtuple == NULL) { - return 0; - } - keywords = parser->keywords + parser->pos; - for (i = 0; i < nkw; i++) { - PyObject *str = PyUnicode_FromString(keywords[i]); - if (str == NULL) { - Py_DECREF(kwtuple); - return 0; - } - PyUnicode_InternInPlace(&str); - PyTuple_SET_ITEM(kwtuple, i, str); - } - parser->kwtuple = kwtuple; - - assert(parser->next == NULL); - parser->next = static_arg_parsers; - static_arg_parsers = parser; - return 1; -} - -static void -parser_clear(struct _PyArg_Parser *parser) -{ - Py_CLEAR(parser->kwtuple); -} - -static PyObject* + return 0; + } + } + + nkw = len - parser->pos; + kwtuple = PyTuple_New(nkw); + if (kwtuple == NULL) { + return 0; + } + keywords = parser->keywords + parser->pos; + for (i = 0; i < nkw; i++) { + PyObject *str = PyUnicode_FromString(keywords[i]); + if (str == NULL) { + Py_DECREF(kwtuple); + return 0; + } + PyUnicode_InternInPlace(&str); + PyTuple_SET_ITEM(kwtuple, i, str); + } + parser->kwtuple = kwtuple; + + assert(parser->next == NULL); + parser->next = static_arg_parsers; + static_arg_parsers = parser; + return 1; +} + +static void +parser_clear(struct _PyArg_Parser *parser) +{ + Py_CLEAR(parser->kwtuple); +} + +static PyObject* find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key) -{ - Py_ssize_t i, nkwargs; - - nkwargs = PyTuple_GET_SIZE(kwnames); +{ + Py_ssize_t i, nkwargs; + + nkwargs = PyTuple_GET_SIZE(kwnames); for (i = 0; i < nkwargs; i++) { - PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); - + PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); + /* kwname == key will normally find a match in since keyword keys should be interned strings; if not retry below in a new loop. */ - if (kwname == key) { - return kwstack[i]; - } + if (kwname == key) { + return kwstack[i]; + } } for (i = 0; i < nkwargs; i++) { PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); assert(PyUnicode_Check(kwname)); - if (_PyUnicode_EQ(kwname, key)) { - return kwstack[i]; - } - } - return NULL; -} - -static int -vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, - PyObject *kwargs, PyObject *kwnames, - struct _PyArg_Parser *parser, - va_list *p_va, int flags) -{ - PyObject *kwtuple; - char msgbuf[512]; - int levels[32]; - const char *format; - const char *msg; - PyObject *keyword; - int i, pos, len; - Py_ssize_t nkwargs; - PyObject *current_arg; - freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; - freelist_t freelist; - PyObject *const *kwstack = NULL; - - freelist.entries = static_entries; - freelist.first_available = 0; - freelist.entries_malloced = 0; - - 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; - } - - kwtuple = parser->kwtuple; - pos = parser->pos; - len = pos + (int)PyTuple_GET_SIZE(kwtuple); - - if (len > STATIC_FREELIST_ENTRIES) { - freelist.entries = PyMem_NEW(freelistentry_t, len); - if (freelist.entries == NULL) { - PyErr_NoMemory(); - return 0; - } - freelist.entries_malloced = 1; - } - - if (kwargs != NULL) { - nkwargs = PyDict_GET_SIZE(kwargs); - } - else if (kwnames != NULL) { - nkwargs = PyTuple_GET_SIZE(kwnames); - kwstack = args + nargs; - } - else { - nkwargs = 0; - } - if (nargs + nkwargs > len) { - /* Adding "keyword" (when nargs == 0) prevents producing wrong error - messages in some special cases (see bpo-31229). */ - PyErr_Format(PyExc_TypeError, - "%.200s%s takes at most %d %sargument%s (%zd given)", - (parser->fname == NULL) ? "function" : parser->fname, - (parser->fname == NULL) ? "" : "()", - len, - (nargs == 0) ? "keyword " : "", - (len == 1) ? "" : "s", - nargs + nkwargs); - return cleanreturn(0, &freelist); - } - if (parser->max < nargs) { - if (parser->max == 0) { - PyErr_Format(PyExc_TypeError, - "%.200s%s takes no positional arguments", - (parser->fname == NULL) ? "function" : parser->fname, - (parser->fname == NULL) ? "" : "()"); - } - else { - PyErr_Format(PyExc_TypeError, + if (_PyUnicode_EQ(kwname, key)) { + return kwstack[i]; + } + } + return NULL; +} + +static int +vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, + PyObject *kwargs, PyObject *kwnames, + struct _PyArg_Parser *parser, + va_list *p_va, int flags) +{ + PyObject *kwtuple; + char msgbuf[512]; + int levels[32]; + const char *format; + const char *msg; + PyObject *keyword; + int i, pos, len; + Py_ssize_t nkwargs; + PyObject *current_arg; + freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; + freelist_t freelist; + PyObject *const *kwstack = NULL; + + freelist.entries = static_entries; + freelist.first_available = 0; + freelist.entries_malloced = 0; + + 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; + } + + kwtuple = parser->kwtuple; + pos = parser->pos; + len = pos + (int)PyTuple_GET_SIZE(kwtuple); + + if (len > STATIC_FREELIST_ENTRIES) { + freelist.entries = PyMem_NEW(freelistentry_t, len); + if (freelist.entries == NULL) { + PyErr_NoMemory(); + return 0; + } + freelist.entries_malloced = 1; + } + + if (kwargs != NULL) { + nkwargs = PyDict_GET_SIZE(kwargs); + } + else if (kwnames != NULL) { + nkwargs = PyTuple_GET_SIZE(kwnames); + kwstack = args + nargs; + } + else { + nkwargs = 0; + } + if (nargs + nkwargs > len) { + /* Adding "keyword" (when nargs == 0) prevents producing wrong error + messages in some special cases (see bpo-31229). */ + PyErr_Format(PyExc_TypeError, + "%.200s%s takes at most %d %sargument%s (%zd given)", + (parser->fname == NULL) ? "function" : parser->fname, + (parser->fname == NULL) ? "" : "()", + len, + (nargs == 0) ? "keyword " : "", + (len == 1) ? "" : "s", + nargs + nkwargs); + return cleanreturn(0, &freelist); + } + if (parser->max < nargs) { + if (parser->max == 0) { + PyErr_Format(PyExc_TypeError, + "%.200s%s takes no positional arguments", + (parser->fname == NULL) ? "function" : parser->fname, + (parser->fname == NULL) ? "" : "()"); + } + else { + PyErr_Format(PyExc_TypeError, "%.200s%s takes %s %d positional argument%s (%zd given)", - (parser->fname == NULL) ? "function" : parser->fname, - (parser->fname == NULL) ? "" : "()", + (parser->fname == NULL) ? "function" : parser->fname, + (parser->fname == NULL) ? "" : "()", (parser->min < parser->max) ? "at most" : "exactly", parser->max, parser->max == 1 ? "" : "s", nargs); - } - return cleanreturn(0, &freelist); - } - - format = parser->format; - /* convert tuple args and keyword args in same loop, using kwtuple to drive process */ - for (i = 0; i < len; i++) { - if (*format == '|') { - format++; - } - if (*format == '$') { - format++; - } - assert(!IS_END_OF_FORMAT(*format)); - - if (i < nargs) { - current_arg = args[i]; - } - else if (nkwargs && i >= pos) { - keyword = PyTuple_GET_ITEM(kwtuple, i - pos); + } + return cleanreturn(0, &freelist); + } + + format = parser->format; + /* convert tuple args and keyword args in same loop, using kwtuple to drive process */ + for (i = 0; i < len; i++) { + if (*format == '|') { + format++; + } + if (*format == '$') { + format++; + } + assert(!IS_END_OF_FORMAT(*format)); + + if (i < nargs) { + current_arg = args[i]; + } + else if (nkwargs && i >= pos) { + keyword = PyTuple_GET_ITEM(kwtuple, i - pos); if (kwargs != NULL) { current_arg = PyDict_GetItemWithError(kwargs, keyword); if (!current_arg && PyErr_Occurred()) { @@ -2200,68 +2200,68 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, current_arg = find_keyword(kwnames, kwstack, keyword); } if (current_arg) { - --nkwargs; - } - } - else { - current_arg = NULL; - } - - if (current_arg) { - msg = convertitem(current_arg, &format, p_va, flags, - levels, msgbuf, sizeof(msgbuf), &freelist); - if (msg) { - seterror(i+1, msg, levels, parser->fname, parser->custom_msg); - return cleanreturn(0, &freelist); - } - continue; - } - - if (i < parser->min) { - /* Less arguments than required */ - if (i < pos) { - Py_ssize_t min = Py_MIN(pos, parser->min); - PyErr_Format(PyExc_TypeError, + --nkwargs; + } + } + else { + current_arg = NULL; + } + + if (current_arg) { + msg = convertitem(current_arg, &format, p_va, flags, + levels, msgbuf, sizeof(msgbuf), &freelist); + if (msg) { + seterror(i+1, msg, levels, parser->fname, parser->custom_msg); + return cleanreturn(0, &freelist); + } + continue; + } + + if (i < parser->min) { + /* Less arguments than required */ + if (i < pos) { + Py_ssize_t min = Py_MIN(pos, parser->min); + PyErr_Format(PyExc_TypeError, "%.200s%s takes %s %d positional argument%s" " (%zd given)", - (parser->fname == NULL) ? "function" : parser->fname, - (parser->fname == NULL) ? "" : "()", - min < parser->max ? "at least" : "exactly", + (parser->fname == NULL) ? "function" : parser->fname, + (parser->fname == NULL) ? "" : "()", + min < parser->max ? "at least" : "exactly", min, min == 1 ? "" : "s", nargs); - } - else { - keyword = PyTuple_GET_ITEM(kwtuple, i - pos); - PyErr_Format(PyExc_TypeError, "%.200s%s missing required " - "argument '%U' (pos %d)", - (parser->fname == NULL) ? "function" : parser->fname, - (parser->fname == NULL) ? "" : "()", - keyword, i+1); - } - return cleanreturn(0, &freelist); - } - /* current code reports success when all required args - * fulfilled and no keyword args left, with no further - * validation. XXX Maybe skip this in debug build ? - */ - if (!nkwargs) { - return cleanreturn(1, &freelist); - } - - /* We are into optional args, skip through to any remaining - * keyword args */ - msg = skipitem(&format, p_va, flags); - assert(msg == NULL); - } - - assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$')); - - 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); + } + else { + keyword = PyTuple_GET_ITEM(kwtuple, i - pos); + PyErr_Format(PyExc_TypeError, "%.200s%s missing required " + "argument '%U' (pos %d)", + (parser->fname == NULL) ? "function" : parser->fname, + (parser->fname == NULL) ? "" : "()", + keyword, i+1); + } + return cleanreturn(0, &freelist); + } + /* current code reports success when all required args + * fulfilled and no keyword args left, with no further + * validation. XXX Maybe skip this in debug build ? + */ + if (!nkwargs) { + return cleanreturn(1, &freelist); + } + + /* We are into optional args, skip through to any remaining + * keyword args */ + msg = skipitem(&format, p_va, flags); + assert(msg == NULL); + } + + assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$')); + + 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); if (kwargs != NULL) { current_arg = PyDict_GetItemWithError(kwargs, keyword); if (!current_arg && PyErr_Occurred()) { @@ -2271,72 +2271,72 @@ vgetargskeywordsfast_impl(PyObject *const *args, Py_ssize_t nargs, else { current_arg = find_keyword(kwnames, kwstack, keyword); } - if (current_arg) { - /* arg present in tuple and in dict */ - PyErr_Format(PyExc_TypeError, - "argument for %.200s%s given by name ('%U') " - "and position (%d)", - (parser->fname == NULL) ? "function" : parser->fname, - (parser->fname == NULL) ? "" : "()", - keyword, i+1); - 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, keyword); - if (match <= 0) { - if (!match) { - PyErr_Format(PyExc_TypeError, + if (current_arg) { + /* arg present in tuple and in dict */ + PyErr_Format(PyExc_TypeError, + "argument for %.200s%s given by name ('%U') " + "and position (%d)", + (parser->fname == NULL) ? "function" : parser->fname, + (parser->fname == NULL) ? "" : "()", + keyword, i+1); + 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, keyword); + if (match <= 0) { + if (!match) { + PyErr_Format(PyExc_TypeError, "'%S' is an invalid keyword " - "argument for %.200s%s", - keyword, - (parser->fname == NULL) ? "this function" : parser->fname, - (parser->fname == NULL) ? "" : "()"); - } - return cleanreturn(0, &freelist); - } - } - } - - return cleanreturn(1, &freelist); -} - -static int -vgetargskeywordsfast(PyObject *args, PyObject *keywords, - struct _PyArg_Parser *parser, va_list *p_va, int flags) -{ - PyObject **stack; - Py_ssize_t nargs; - - if (args == NULL - || !PyTuple_Check(args) - || (keywords != NULL && !PyDict_Check(keywords))) - { - PyErr_BadInternalCall(); - return 0; - } - + "argument for %.200s%s", + keyword, + (parser->fname == NULL) ? "this function" : parser->fname, + (parser->fname == NULL) ? "" : "()"); + } + return cleanreturn(0, &freelist); + } + } + } + + return cleanreturn(1, &freelist); +} + +static int +vgetargskeywordsfast(PyObject *args, PyObject *keywords, + struct _PyArg_Parser *parser, va_list *p_va, int flags) +{ + PyObject **stack; + Py_ssize_t nargs; + + if (args == NULL + || !PyTuple_Check(args) + || (keywords != NULL && !PyDict_Check(keywords))) + { + PyErr_BadInternalCall(); + return 0; + } + stack = _PyTuple_ITEMS(args); - nargs = PyTuple_GET_SIZE(args); - return vgetargskeywordsfast_impl(stack, nargs, keywords, NULL, - parser, p_va, flags); -} - - + nargs = PyTuple_GET_SIZE(args); + return vgetargskeywordsfast_impl(stack, nargs, keywords, NULL, + parser, p_va, flags); +} + + #undef _PyArg_UnpackKeywords PyObject * const * @@ -2541,190 +2541,190 @@ _PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, } -static const char * -skipitem(const char **p_format, va_list *p_va, int flags) -{ - const char *format = *p_format; - char c = *format++; - - switch (c) { - - /* - * codes that take a single data pointer as an argument - * (the type of the pointer is irrelevant) - */ - - case 'b': /* byte -- very short int */ - case 'B': /* byte as bitfield */ - case 'h': /* short int */ - case 'H': /* short int as bitfield */ - case 'i': /* int */ - case 'I': /* int sized bitfield */ - case 'l': /* long int */ - case 'k': /* long int sized bitfield */ - case 'L': /* long long */ - case 'K': /* long long sized bitfield */ - case 'n': /* Py_ssize_t */ - case 'f': /* float */ - case 'd': /* double */ - case 'D': /* complex double */ - case 'c': /* char */ - case 'C': /* unicode char */ - case 'p': /* boolean predicate */ - case 'S': /* string object */ - case 'Y': /* string object */ - case 'U': /* unicode string object */ - { - if (p_va != NULL) { - (void) va_arg(*p_va, void *); - } - break; - } - - /* string codes */ - - case 'e': /* string with encoding */ - { - if (p_va != NULL) { - (void) va_arg(*p_va, const char *); - } - if (!(*format == 's' || *format == 't')) - /* after 'e', only 's' and 't' is allowed */ - goto err; - format++; - } - /* fall through */ - - case 's': /* string */ - case 'z': /* string or None */ - case 'y': /* bytes */ - case 'u': /* unicode string */ - case 'Z': /* unicode string or None */ - case 'w': /* buffer, read-write */ - { - if (p_va != NULL) { - (void) va_arg(*p_va, char **); - } - if (*format == '#') { - if (p_va != NULL) { - if (flags & FLAG_SIZE_T) - (void) va_arg(*p_va, Py_ssize_t *); +static const char * +skipitem(const char **p_format, va_list *p_va, int flags) +{ + const char *format = *p_format; + char c = *format++; + + switch (c) { + + /* + * codes that take a single data pointer as an argument + * (the type of the pointer is irrelevant) + */ + + case 'b': /* byte -- very short int */ + case 'B': /* byte as bitfield */ + case 'h': /* short int */ + case 'H': /* short int as bitfield */ + case 'i': /* int */ + case 'I': /* int sized bitfield */ + case 'l': /* long int */ + case 'k': /* long int sized bitfield */ + case 'L': /* long long */ + case 'K': /* long long sized bitfield */ + case 'n': /* Py_ssize_t */ + case 'f': /* float */ + case 'd': /* double */ + case 'D': /* complex double */ + case 'c': /* char */ + case 'C': /* unicode char */ + case 'p': /* boolean predicate */ + case 'S': /* string object */ + case 'Y': /* string object */ + case 'U': /* unicode string object */ + { + if (p_va != NULL) { + (void) va_arg(*p_va, void *); + } + break; + } + + /* string codes */ + + case 'e': /* string with encoding */ + { + if (p_va != NULL) { + (void) va_arg(*p_va, const char *); + } + if (!(*format == 's' || *format == 't')) + /* after 'e', only 's' and 't' is allowed */ + goto err; + format++; + } + /* fall through */ + + case 's': /* string */ + case 'z': /* string or None */ + case 'y': /* bytes */ + case 'u': /* unicode string */ + case 'Z': /* unicode string or None */ + case 'w': /* buffer, read-write */ + { + if (p_va != NULL) { + (void) va_arg(*p_va, char **); + } + if (*format == '#') { + if (p_va != NULL) { + if (flags & FLAG_SIZE_T) + (void) va_arg(*p_va, Py_ssize_t *); else { if (PyErr_WarnEx(PyExc_DeprecationWarning, "PY_SSIZE_T_CLEAN will be required for '#' formats", 1)) { return NULL; } - (void) va_arg(*p_va, int *); + (void) va_arg(*p_va, int *); } - } - format++; - } else if ((c == 's' || c == 'z' || c == 'y' || c == 'w') - && *format == '*') - { - format++; - } - break; - } - - case 'O': /* object */ - { - if (*format == '!') { - format++; - if (p_va != NULL) { - (void) va_arg(*p_va, PyTypeObject*); - (void) va_arg(*p_va, PyObject **); - } - } - else if (*format == '&') { - typedef int (*converter)(PyObject *, void *); - if (p_va != NULL) { - (void) va_arg(*p_va, converter); - (void) va_arg(*p_va, void *); - } - format++; - } - else { - if (p_va != NULL) { - (void) va_arg(*p_va, PyObject **); - } - } - break; - } - - case '(': /* bypass tuple, not handled at all previously */ - { - const char *msg; - for (;;) { - if (*format==')') - break; - if (IS_END_OF_FORMAT(*format)) - return "Unmatched left paren in format " - "string"; - msg = skipitem(&format, p_va, flags); - if (msg) - return msg; - } - format++; - break; - } - - case ')': - return "Unmatched right paren in format string"; - - default: -err: - return "impossible<bad format char>"; - - } - - *p_format = format; - return NULL; -} - - + } + format++; + } else if ((c == 's' || c == 'z' || c == 'y' || c == 'w') + && *format == '*') + { + format++; + } + break; + } + + case 'O': /* object */ + { + if (*format == '!') { + format++; + if (p_va != NULL) { + (void) va_arg(*p_va, PyTypeObject*); + (void) va_arg(*p_va, PyObject **); + } + } + else if (*format == '&') { + typedef int (*converter)(PyObject *, void *); + if (p_va != NULL) { + (void) va_arg(*p_va, converter); + (void) va_arg(*p_va, void *); + } + format++; + } + else { + if (p_va != NULL) { + (void) va_arg(*p_va, PyObject **); + } + } + break; + } + + case '(': /* bypass tuple, not handled at all previously */ + { + const char *msg; + for (;;) { + if (*format==')') + break; + if (IS_END_OF_FORMAT(*format)) + return "Unmatched left paren in format " + "string"; + msg = skipitem(&format, p_va, flags); + if (msg) + return msg; + } + format++; + break; + } + + case ')': + return "Unmatched right paren in format string"; + + default: +err: + return "impossible<bad format char>"; + + } + + *p_format = format; + return NULL; +} + + #undef _PyArg_CheckPositional int _PyArg_CheckPositional(const char *name, Py_ssize_t nargs, Py_ssize_t min, Py_ssize_t max) -{ - assert(min >= 0); - assert(min <= max); - - if (nargs < min) { - if (name != NULL) - PyErr_Format( - PyExc_TypeError, +{ + assert(min >= 0); + assert(min <= max); + + if (nargs < min) { + if (name != NULL) + PyErr_Format( + PyExc_TypeError, "%.200s expected %s%zd argument%s, got %zd", name, (min == max ? "" : "at least "), min, min == 1 ? "" : "s", nargs); - else - PyErr_Format( - PyExc_TypeError, + else + PyErr_Format( + PyExc_TypeError, "unpacked tuple should have %s%zd element%s," - " but has %zd", + " but has %zd", (min == max ? "" : "at least "), min, min == 1 ? "" : "s", nargs); - return 0; - } - - if (nargs == 0) { - return 1; - } - - if (nargs > max) { - if (name != NULL) - PyErr_Format( - PyExc_TypeError, + return 0; + } + + if (nargs == 0) { + return 1; + } + + if (nargs > max) { + if (name != NULL) + PyErr_Format( + PyExc_TypeError, "%.200s expected %s%zd argument%s, got %zd", name, (min == max ? "" : "at most "), max, max == 1 ? "" : "s", nargs); - else - PyErr_Format( - PyExc_TypeError, + else + PyErr_Format( + PyExc_TypeError, "unpacked tuple should have %s%zd element%s," - " but has %zd", + " but has %zd", (min == max ? "" : "at most "), max, max == 1 ? "" : "s", nargs); - return 0; - } - + return 0; + } + return 1; } @@ -2739,102 +2739,102 @@ unpack_stack(PyObject *const *args, Py_ssize_t nargs, const char *name, 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; - } + 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_ITEMS(args); - nargs = PyTuple_GET_SIZE(args); - -#ifdef HAVE_STDARG_PROTOTYPES - va_start(vargs, max); -#else - va_start(vargs); -#endif - retval = unpack_stack(stack, nargs, name, min, max, vargs); - va_end(vargs); - return retval; -} - -int -_PyArg_UnpackStack(PyObject *const *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; -} - - -#undef _PyArg_NoKeywords + nargs = PyTuple_GET_SIZE(args); + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, max); +#else + va_start(vargs); +#endif + retval = unpack_stack(stack, nargs, name, min, max, vargs); + va_end(vargs); + return retval; +} + +int +_PyArg_UnpackStack(PyObject *const *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; +} + + +#undef _PyArg_NoKeywords #undef _PyArg_NoKwnames -#undef _PyArg_NoPositional - -/* For type constructors that don't take keyword args - * - * Sets a TypeError and returns 0 if the args/kwargs is - * not empty, returns 1 otherwise - */ -int -_PyArg_NoKeywords(const char *funcname, PyObject *kwargs) -{ - if (kwargs == NULL) { - return 1; - } - if (!PyDict_CheckExact(kwargs)) { - PyErr_BadInternalCall(); - return 0; - } - if (PyDict_GET_SIZE(kwargs) == 0) { - return 1; - } - - PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", - funcname); - return 0; -} - -int -_PyArg_NoPositional(const char *funcname, PyObject *args) -{ - if (args == NULL) - return 1; - if (!PyTuple_CheckExact(args)) { - PyErr_BadInternalCall(); - return 0; - } - if (PyTuple_GET_SIZE(args) == 0) - return 1; - - PyErr_Format(PyExc_TypeError, "%.200s() takes no positional arguments", - funcname); - return 0; -} - +#undef _PyArg_NoPositional + +/* For type constructors that don't take keyword args + * + * Sets a TypeError and returns 0 if the args/kwargs is + * not empty, returns 1 otherwise + */ +int +_PyArg_NoKeywords(const char *funcname, PyObject *kwargs) +{ + if (kwargs == NULL) { + return 1; + } + if (!PyDict_CheckExact(kwargs)) { + PyErr_BadInternalCall(); + return 0; + } + if (PyDict_GET_SIZE(kwargs) == 0) { + return 1; + } + + PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", + funcname); + return 0; +} + +int +_PyArg_NoPositional(const char *funcname, PyObject *args) +{ + if (args == NULL) + return 1; + if (!PyTuple_CheckExact(args)) { + PyErr_BadInternalCall(); + return 0; + } + if (PyTuple_GET_SIZE(args) == 0) + return 1; + + PyErr_Format(PyExc_TypeError, "%.200s() takes no positional arguments", + funcname); + return 0; +} + int _PyArg_NoKwnames(const char *funcname, PyObject *kwnames) { @@ -2852,19 +2852,19 @@ _PyArg_NoKwnames(const char *funcname, PyObject *kwnames) return 0; } -void -_PyArg_Fini(void) -{ - struct _PyArg_Parser *tmp, *s = static_arg_parsers; - while (s) { - tmp = s->next; - s->next = NULL; - parser_clear(s); - s = tmp; - } - static_arg_parsers = NULL; -} - -#ifdef __cplusplus -}; -#endif +void +_PyArg_Fini(void) +{ + struct _PyArg_Parser *tmp, *s = static_arg_parsers; + while (s) { + tmp = s->next; + s->next = NULL; + parser_clear(s); + s = tmp; + } + static_arg_parsers = NULL; +} + +#ifdef __cplusplus +}; +#endif |