From fe54dd8a08b171c20bafe0759c17464a2642030d Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 17 Jan 2017 02:33:55 +0100 Subject: Add _PyArg_UnpackStack() function helper Issue #29286. --- Include/modsupport.h | 10 +++++++ Python/getargs.c | 73 +++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/Include/modsupport.h b/Include/modsupport.h index e6713e2..e464a1c 100644 --- a/Include/modsupport.h +++ b/Include/modsupport.h @@ -47,7 +47,16 @@ PyAPI_FUNC(int) PyArg_UnpackTuple(PyObject *, const char *, Py_ssize_t, Py_ssize PyAPI_FUNC(PyObject *) Py_BuildValue(const char *, ...); PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); #endif + #ifndef Py_LIMITED_API +PyAPI_FUNC(int) _PyArg_UnpackStack( + PyObject **args, + Py_ssize_t nargs, + const char *name, + Py_ssize_t min, + Py_ssize_t max, + ...); + PyAPI_FUNC(int) _PyArg_NoKeywords(const char *funcname, PyObject *kwargs); PyAPI_FUNC(int) _PyArg_NoStackKeywords(const char *funcname, PyObject *kwnames); PyAPI_FUNC(int) _PyArg_NoPositional(const char *funcname, PyObject *args); @@ -56,6 +65,7 @@ PyAPI_FUNC(int) PyArg_VaParse(PyObject *, const char *, va_list); PyAPI_FUNC(int) PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, const char *, char **, va_list); #endif + PyAPI_FUNC(PyObject *) Py_VaBuildValue(const char *, va_list); #ifndef Py_LIMITED_API PyAPI_FUNC(PyObject **) _Py_VaBuildStack( diff --git a/Python/getargs.c b/Python/getargs.c index e3611d8..47b00af 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2363,21 +2363,16 @@ err: } -int -PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) +static int +PyArg_UnpackStack_impl(PyObject **args, Py_ssize_t l, const char *name, + Py_ssize_t min, Py_ssize_t max, va_list vargs) { - Py_ssize_t i, l; + Py_ssize_t i; PyObject **o; - va_list vargs; assert(min >= 0); assert(min <= max); - if (!PyTuple_Check(args)) { - PyErr_SetString(PyExc_SystemError, - "PyArg_UnpackTuple() argument list is not a tuple"); - return 0; - } - l = PyTuple_GET_SIZE(args); + if (l < min) { if (name != NULL) PyErr_Format( @@ -2392,8 +2387,11 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m (min == max ? "" : "at least "), min, l); return 0; } - if (l == 0) + + if (l == 0) { return 1; + } + if (l > max) { if (name != NULL) PyErr_Format( @@ -2409,17 +2407,54 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m return 0; } + for (i = 0; i < l; i++) { + o = va_arg(vargs, PyObject **); + *o = args[i]; + } + return 1; +} + +int +PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) +{ + PyObject **stack; + Py_ssize_t nargs; + int retval; + va_list vargs; + + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_SystemError, + "PyArg_UnpackTuple() argument list is not a tuple"); + return 0; + } + stack = &PyTuple_GET_ITEM(args, 0); + nargs = PyTuple_GET_SIZE(args); + #ifdef HAVE_STDARG_PROTOTYPES va_start(vargs, max); #else va_start(vargs); #endif - for (i = 0; i < l; i++) { - o = va_arg(vargs, PyObject **); - *o = PyTuple_GET_ITEM(args, i); - } + retval = PyArg_UnpackStack_impl(stack, nargs, name, min, max, vargs); va_end(vargs); - return 1; + return retval; +} + +int +_PyArg_UnpackStack(PyObject **args, Py_ssize_t nargs, const char *name, + Py_ssize_t min, Py_ssize_t max, ...) +{ + int retval; + va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, max); +#else + va_start(vargs); +#endif + retval = PyArg_UnpackStack_impl(args, nargs, name, min, max, vargs); + va_end(vargs); + return retval; } @@ -2431,8 +2466,9 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m int _PyArg_NoKeywords(const char *funcname, PyObject *kwargs) { - if (kwargs == NULL) + if (kwargs == NULL) { return 1; + } if (!PyDict_CheckExact(kwargs)) { PyErr_BadInternalCall(); return 0; @@ -2450,8 +2486,9 @@ _PyArg_NoKeywords(const char *funcname, PyObject *kwargs) int _PyArg_NoStackKeywords(const char *funcname, PyObject *kwnames) { - if (kwnames == NULL) + if (kwnames == NULL) { return 1; + } assert(PyTuple_CheckExact(kwnames)); if (PyTuple_GET_SIZE(kwnames) == 0) { return 1; -- cgit v0.12