diff options
Diffstat (limited to 'Python/getargs.c')
| -rw-r--r-- | Python/getargs.c | 345 | 
1 files changed, 210 insertions, 135 deletions
| diff --git a/Python/getargs.c b/Python/getargs.c index 616c6eb107..47b00af442 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -26,7 +26,9 @@ int _PyArg_VaParseTupleAndKeywordsFast(PyObject *, PyObject *,  #ifdef HAVE_DECLSPEC_DLL  /* Export functions */  PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, const char *, ...); -PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames, +PyAPI_FUNC(int) _PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, +                                        const char *format, ...); +PyAPI_FUNC(int) _PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,                                          struct _PyArg_Parser *parser, ...);  PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, const char *, ...);  PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *, @@ -66,6 +68,8 @@ typedef struct {  #define STATIC_FREELIST_ENTRIES 8  /* Forward */ +static int vgetargs1_impl(PyObject *args, PyObject **stack, Py_ssize_t nargs, +                          const char *format, va_list *p_va, int flags);  static int vgetargs1(PyObject *, const char *, va_list *, int);  static void seterror(Py_ssize_t, const char *, int *, const char *, const char *);  static const char *convertitem(PyObject *, const char **, va_list *, int, int *, @@ -74,7 +78,7 @@ static const char *converttuple(PyObject *, const char **, va_list *, int,                                  int *, char *, size_t, int, freelist_t *);  static const char *convertsimple(PyObject *, const char **, va_list *, int,                                   char *, size_t, freelist_t *); -static Py_ssize_t convertbuffer(PyObject *, void **p, const char **); +static Py_ssize_t convertbuffer(PyObject *, const void **p, const char **);  static int getbuffer(PyObject *, Py_buffer *, const char**);  static int vgetargskeywords(PyObject *, PyObject *, @@ -138,6 +142,31 @@ _PyArg_ParseTuple_SizeT(PyObject *args, const char *format, ...)  int +_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, const char *format, ...) +{ +    int retval; +    va_list va; + +    va_start(va, format); +    retval = vgetargs1_impl(NULL, args, nargs, format, &va, 0); +    va_end(va); +    return retval; +} + +int +_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, const char *format, ...) +{ +    int retval; +    va_list va; + +    va_start(va, format); +    retval = vgetargs1_impl(NULL, args, nargs, format, &va, FLAG_SIZE_T); +    va_end(va); +    return retval; +} + + +int  PyArg_VaParse(PyObject *args, const char *format, va_list va)  {      va_list lva; @@ -220,7 +249,8 @@ cleanreturn(int retval, freelist_t *freelist)  static int -vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) +vgetargs1_impl(PyObject *compat_args, PyObject **stack, Py_ssize_t nargs, const char *format, +               va_list *p_va, int flags)  {      char msgbuf[256];      int levels[32]; @@ -231,17 +261,18 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)      int level = 0;      int endfmt = 0;      const char *formatsave = format; -    Py_ssize_t i, len; +    Py_ssize_t i;      const char *msg;      int compat = flags & FLAG_COMPAT;      freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];      freelist_t freelist; +    assert(nargs == 0 || stack != NULL); +      freelist.entries = static_entries;      freelist.first_available = 0;      freelist.entries_malloced = 0; -    assert(compat || (args != (PyObject*)NULL));      flags = flags & ~FLAG_COMPAT;      while (endfmt == 0) { @@ -305,7 +336,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)      if (compat) {          if (max == 0) { -            if (args == NULL) +            if (compat_args == NULL)                  return 1;              PyErr_Format(PyExc_TypeError,                           "%.200s%s takes no arguments", @@ -314,14 +345,14 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)              return cleanreturn(0, &freelist);          }          else if (min == 1 && max == 1) { -            if (args == NULL) { +            if (compat_args == NULL) {                  PyErr_Format(PyExc_TypeError,                               "%.200s%s takes at least one argument",                               fname==NULL ? "function" : fname,                               fname==NULL ? "" : "()");                  return cleanreturn(0, &freelist);              } -            msg = convertitem(args, &format, p_va, flags, levels, +            msg = convertitem(compat_args, &format, p_va, flags, levels,                                msgbuf, sizeof(msgbuf), &freelist);              if (msg == NULL)                  return cleanreturn(1, &freelist); @@ -335,34 +366,26 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)          }      } -    if (!PyTuple_Check(args)) { -        PyErr_SetString(PyExc_SystemError, -            "new style getargs format but argument is not a tuple"); -        return cleanreturn(0, &freelist); -    } - -    len = PyTuple_GET_SIZE(args); - -    if (len < min || max < len) { +    if (nargs < min || max < nargs) {          if (message == NULL)              PyErr_Format(PyExc_TypeError,                           "%.150s%s takes %s %d argument%s (%ld given)",                           fname==NULL ? "function" : fname,                           fname==NULL ? "" : "()",                           min==max ? "exactly" -                         : len < min ? "at least" : "at most", -                         len < min ? min : max, -                         (len < min ? min : max) == 1 ? "" : "s", -                         Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); +                         : nargs < min ? "at least" : "at most", +                         nargs < min ? min : max, +                         (nargs < min ? min : max) == 1 ? "" : "s", +                         Py_SAFE_DOWNCAST(nargs, Py_ssize_t, long));          else              PyErr_SetString(PyExc_TypeError, message);          return cleanreturn(0, &freelist);      } -    for (i = 0; i < len; i++) { +    for (i = 0; i < nargs; i++) {          if (*format == '|')              format++; -        msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, +        msg = convertitem(stack[i], &format, p_va,                            flags, levels, msgbuf,                            sizeof(msgbuf), &freelist);          if (msg) { @@ -382,6 +405,31 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags)      return cleanreturn(1, &freelist);  } +static int +vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) +{ +    PyObject **stack; +    Py_ssize_t nargs; + +    if (!(flags & FLAG_COMPAT)) { +        assert(args != NULL); + +        if (!PyTuple_Check(args)) { +            PyErr_SetString(PyExc_SystemError, +                "new style getargs format but argument is not a tuple"); +            return 0; +        } + +        stack = &PyTuple_GET_ITEM(args, 0); +        nargs = PyTuple_GET_SIZE(args); +    } +    else { +        stack = NULL; +        nargs = 0; +    } + +    return vgetargs1_impl(args, stack, nargs, format, p_va, flags); +}  static void @@ -625,7 +673,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,      const char *format = *p_format;      char c = *format++; -    char *sarg; +    const char *sarg;      switch (c) { @@ -897,7 +945,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,              }              break;          } -        count = convertbuffer(arg, p, &buf); +        count = convertbuffer(arg, (const void **)p, &buf);          if (count < 0)              return converterr(buf, arg, msgbuf, bufsize);          if (*format == '#') { @@ -928,7 +976,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,                  if (sarg == NULL)                      return converterr(CONV_UNICODE,                                        arg, msgbuf, bufsize); -                PyBuffer_FillInfo(p, arg, sarg, len, 1, 0); +                PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0);              }              else { /* any bytes-like object */                  const char *buf; @@ -943,7 +991,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,              format++;          } else if (*format == '#') { /* a string or read-only bytes-like object */              /* "s#" or "z#" */ -            void **p = (void **)va_arg(*p_va, char **); +            const void **p = (const void **)va_arg(*p_va, const char **);              FETCH_SIZE;              if (c == 'z' && arg == Py_None) { @@ -970,7 +1018,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,              format++;          } else {              /* "s" or "z" */ -            char **p = va_arg(*p_va, char **); +            const char **p = va_arg(*p_va, const char **);              Py_ssize_t len;              sarg = NULL; @@ -1027,7 +1075,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,                  *p = PyUnicode_AsUnicodeAndSize(arg, &len);                  if (*p == NULL)                      RETURN_ERR_OCCURRED; -                if (Py_UNICODE_strlen(*p) != (size_t)len) { +                if (wcslen(*p) != (size_t)len) {                      PyErr_SetString(PyExc_ValueError, "embedded null character");                      RETURN_ERR_OCCURRED;                  } @@ -1074,9 +1122,14 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,              (PyBytes_Check(arg) || PyByteArray_Check(arg))) {              s = arg;              Py_INCREF(s); -            if (PyObject_AsCharBuffer(s, &ptr, &size) < 0) -                return converterr("(AsCharBuffer failed)", -                                  arg, msgbuf, bufsize); +            if (PyBytes_Check(arg)) { +                size = PyBytes_GET_SIZE(s); +                ptr = PyBytes_AS_STRING(s); +            } +            else { +                size = PyByteArray_GET_SIZE(s); +                ptr = PyByteArray_AS_STRING(s); +            }          }          else if (PyUnicode_Check(arg)) {              /* Encode object; use default error handling */ @@ -1300,7 +1353,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags,  }  static Py_ssize_t -convertbuffer(PyObject *arg, void **p, const char **errmsg) +convertbuffer(PyObject *arg, const void **p, const char **errmsg)  {      PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer;      Py_ssize_t count; @@ -1448,14 +1501,6 @@ _PyArg_ParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,      int retval;      va_list va; -    if ((args == NULL || !PyTuple_Check(args)) || -        (keywords != NULL && !PyDict_Check(keywords)) || -        parser == NULL) -    { -        PyErr_BadInternalCall(); -        return 0; -    } -      va_start(va, parser);      retval = vgetargskeywordsfast(args, keywords, parser, &va, 0);      va_end(va); @@ -1469,14 +1514,6 @@ _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,      int retval;      va_list va; -    if ((args == NULL || !PyTuple_Check(args)) || -        (keywords != NULL && !PyDict_Check(keywords)) || -        parser == NULL) -    { -        PyErr_BadInternalCall(); -        return 0; -    } -      va_start(va, parser);      retval = vgetargskeywordsfast(args, keywords, parser, &va, FLAG_SIZE_T);      va_end(va); @@ -1484,19 +1521,12 @@ _PyArg_ParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,  }  int -_PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, PyObject *kwnames, +_PyArg_ParseStackAndKeywords(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,                    struct _PyArg_Parser *parser, ...)  {      int retval;      va_list va; -    if ((kwnames != NULL && !PyTuple_Check(kwnames)) || -        parser == NULL) -    { -        PyErr_BadInternalCall(); -        return 0; -    } -      va_start(va, parser);      retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, 0);      va_end(va); @@ -1504,19 +1534,12 @@ _PyArg_ParseStack(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,  }  int -_PyArg_ParseStack_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames, +_PyArg_ParseStackAndKeywords_SizeT(PyObject **args, Py_ssize_t nargs, PyObject *kwnames,                          struct _PyArg_Parser *parser, ...)  {      int retval;      va_list va; -    if ((kwnames != NULL && !PyTuple_Check(kwnames)) || -        parser == NULL) -    { -        PyErr_BadInternalCall(); -        return 0; -    } -      va_start(va, parser);      retval = vgetargskeywordsfast_impl(args, nargs, NULL, kwnames, parser, &va, FLAG_SIZE_T);      va_end(va); @@ -1531,14 +1554,6 @@ _PyArg_VaParseTupleAndKeywordsFast(PyObject *args, PyObject *keywords,      int retval;      va_list lva; -    if ((args == NULL || !PyTuple_Check(args)) || -        (keywords != NULL && !PyDict_Check(keywords)) || -        parser == NULL) -    { -        PyErr_BadInternalCall(); -        return 0; -    } -      va_copy(lva, va);      retval = vgetargskeywordsfast(args, keywords, parser, &lva, 0); @@ -1553,14 +1568,6 @@ _PyArg_VaParseTupleAndKeywordsFast_SizeT(PyObject *args, PyObject *keywords,      int retval;      va_list lva; -    if ((args == NULL || !PyTuple_Check(args)) || -        (keywords != NULL && !PyDict_Check(keywords)) || -        parser == NULL) -    { -        PyErr_BadInternalCall(); -        return 0; -    } -      va_copy(lva, va);      retval = vgetargskeywordsfast(args, keywords, parser, &lva, FLAG_SIZE_T); @@ -1586,7 +1593,7 @@ PyArg_ValidateKeywordArguments(PyObject *kwargs)  #define IS_END_OF_FORMAT(c) (c == '\0' || c == ';' || c == ':')  static int -vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, +vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format,                   char **kwlist, va_list *p_va, int flags)  {      char msgbuf[512]; @@ -1596,7 +1603,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,      int max = INT_MAX;      int i, pos, len;      int skip = 0; -    Py_ssize_t nargs, nkeywords; +    Py_ssize_t nargs, nkwargs;      PyObject *current_arg;      freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];      freelist_t freelist; @@ -1606,7 +1613,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,      freelist.entries_malloced = 0;      assert(args != NULL && PyTuple_Check(args)); -    assert(keywords == NULL || PyDict_Check(keywords)); +    assert(kwargs == NULL || PyDict_Check(kwargs));      assert(format != NULL);      assert(kwlist != NULL);      assert(p_va != NULL); @@ -1645,15 +1652,15 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,      }      nargs = PyTuple_GET_SIZE(args); -    nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); -    if (nargs + nkeywords > len) { +    nkwargs = (kwargs == NULL) ? 0 : PyDict_GET_SIZE(kwargs); +    if (nargs + nkwargs > len) {          PyErr_Format(PyExc_TypeError,                       "%s%s takes at most %d argument%s (%zd given)",                       (fname == NULL) ? "function" : fname,                       (fname == NULL) ? "" : "()",                       len,                       (len == 1) ? "" : "s", -                     nargs + nkeywords); +                     nargs + nkwargs);          return cleanreturn(0, &freelist);      } @@ -1714,14 +1721,14 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,          }          if (!skip) {              current_arg = NULL; -            if (nkeywords && i >= pos) { -                current_arg = PyDict_GetItemString(keywords, keyword); +            if (nkwargs && i >= pos) { +                current_arg = PyDict_GetItemString(kwargs, keyword);                  if (!current_arg && PyErr_Occurred()) {                      return cleanreturn(0, &freelist);                  }              }              if (current_arg) { -                --nkeywords; +                --nkwargs;                  if (i < nargs) {                      /* arg present in tuple and in dict */                      PyErr_Format(PyExc_TypeError, @@ -1765,7 +1772,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,               * fulfilled and no keyword args left, with no further               * validation. XXX Maybe skip this in debug build ?               */ -            if (!nkeywords && !skip) { +            if (!nkwargs && !skip) {                  return cleanreturn(1, &freelist);              }          } @@ -1797,10 +1804,10 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format,      }      /* make sure there are no extraneous keyword arguments */ -    if (nkeywords > 0) { +    if (nkwargs > 0) {          PyObject *key, *value;          Py_ssize_t pos = 0; -        while (PyDict_Next(keywords, &pos, &key, &value)) { +        while (PyDict_Next(kwargs, &pos, &key, &value)) {              int match = 0;              if (!PyUnicode_Check(key)) {                  PyErr_SetString(PyExc_TypeError, @@ -1983,7 +1990,7 @@ find_keyword(PyObject *kwnames, PyObject **kwstack, PyObject *key)  static int  vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs, -                          PyObject *keywords, PyObject *kwnames, +                          PyObject *kwargs, PyObject *kwnames,                            struct _PyArg_Parser *parser,                            va_list *p_va, int flags)  { @@ -1994,7 +2001,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,      const char *msg;      PyObject *keyword;      int i, pos, len; -    Py_ssize_t nkeywords; +    Py_ssize_t nkwargs;      PyObject *current_arg;      freelistentry_t static_entries[STATIC_FREELIST_ENTRIES];      freelist_t freelist; @@ -2004,13 +2011,21 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,      freelist.first_available = 0;      freelist.entries_malloced = 0; -    assert(keywords == NULL || PyDict_Check(keywords)); -    assert(kwnames == NULL || PyTuple_Check(kwnames)); -    assert((keywords != NULL || kwnames != NULL) -           || (keywords == NULL && kwnames == NULL)); -    assert(parser != NULL); +    assert(kwargs == NULL || PyDict_Check(kwargs)); +    assert((kwargs != NULL || kwnames != NULL) +           || (kwargs == NULL && kwnames == NULL));      assert(p_va != NULL); +    if (parser == NULL) { +        PyErr_BadInternalCall(); +        return 0; +    } + +    if (kwnames != NULL && !PyTuple_Check(kwnames)) { +        PyErr_BadInternalCall(); +        return 0; +    } +      if (!parser_init(parser)) {          return 0;      } @@ -2028,24 +2043,24 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,          freelist.entries_malloced = 1;      } -    if (keywords != NULL) { -        nkeywords = PyDict_Size(keywords); +    if (kwargs != NULL) { +        nkwargs = PyDict_GET_SIZE(kwargs);      }      else if (kwnames != NULL) { -        nkeywords = PyTuple_GET_SIZE(kwnames); +        nkwargs = PyTuple_GET_SIZE(kwnames);          kwstack = args + nargs;      }      else { -        nkeywords = 0; +        nkwargs = 0;      } -    if (nargs + nkeywords > len) { +    if (nargs + nkwargs > len) {          PyErr_Format(PyExc_TypeError,                       "%s%s takes at most %d argument%s (%zd given)",                       (parser->fname == NULL) ? "function" : parser->fname,                       (parser->fname == NULL) ? "" : "()",                       len,                       (len == 1) ? "" : "s", -                     nargs + nkeywords); +                     nargs + nkwargs);          return cleanreturn(0, &freelist);      }      if (parser->max < nargs) { @@ -2069,9 +2084,9 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,          assert(!IS_END_OF_FORMAT(*format));          current_arg = NULL; -        if (nkeywords && i >= pos) { -            if (keywords != NULL) { -                current_arg = PyDict_GetItem(keywords, keyword); +        if (nkwargs && i >= pos) { +            if (kwargs != NULL) { +                current_arg = PyDict_GetItem(kwargs, keyword);                  if (!current_arg && PyErr_Occurred()) {                      return cleanreturn(0, &freelist);                  } @@ -2081,7 +2096,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,              }          }          if (current_arg) { -            --nkeywords; +            --nkwargs;              if (i < nargs) {                  /* arg present in tuple and in dict */                  PyErr_Format(PyExc_TypeError, @@ -2125,7 +2140,7 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,           * fulfilled and no keyword args left, with no further           * validation. XXX Maybe skip this in debug build ?           */ -        if (!nkeywords) { +        if (!nkwargs) {              return cleanreturn(1, &freelist);          } @@ -2138,11 +2153,11 @@ vgetargskeywordsfast_impl(PyObject **args, Py_ssize_t nargs,      assert(IS_END_OF_FORMAT(*format) || (*format == '|') || (*format == '$'));      /* make sure there are no extraneous keyword arguments */ -    if (nkeywords > 0) { -        if (keywords != NULL) { +    if (nkwargs > 0) { +        if (kwargs != NULL) {              PyObject *key, *value;              Py_ssize_t pos = 0; -            while (PyDict_Next(keywords, &pos, &key, &value)) { +            while (PyDict_Next(kwargs, &pos, &key, &value)) {                  int match;                  if (!PyUnicode_Check(key)) {                      PyErr_SetString(PyExc_TypeError, @@ -2199,7 +2214,13 @@ vgetargskeywordsfast(PyObject *args, PyObject *keywords,      PyObject **stack;      Py_ssize_t nargs; -    assert(args != NULL && PyTuple_Check(args)); +    if (args == NULL +        || !PyTuple_Check(args) +        || (keywords != NULL && !PyDict_Check(keywords))) +    { +        PyErr_BadInternalCall(); +        return 0; +    }      stack = &PyTuple_GET_ITEM(args, 0);      nargs = PyTuple_GET_SIZE(args); @@ -2342,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( @@ -2371,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( @@ -2388,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;  } @@ -2408,16 +2464,35 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m   * not empty, returns 1 otherwise   */  int -_PyArg_NoKeywords(const char *funcname, PyObject *kw) +_PyArg_NoKeywords(const char *funcname, PyObject *kwargs)  { -    if (kw == NULL) +    if (kwargs == NULL) {          return 1; -    if (!PyDict_CheckExact(kw)) { +    } +    if (!PyDict_CheckExact(kwargs)) {          PyErr_BadInternalCall();          return 0;      } -    if (PyDict_Size(kw) == 0) +    if (PyDict_GET_SIZE(kwargs) == 0) {          return 1; +    } + +    PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments", +                    funcname); +    return 0; +} + + +int +_PyArg_NoStackKeywords(const char *funcname, PyObject *kwnames) +{ +    if (kwnames == NULL) { +        return 1; +    } +    assert(PyTuple_CheckExact(kwnames)); +    if (PyTuple_GET_SIZE(kwnames) == 0) { +        return 1; +    }      PyErr_Format(PyExc_TypeError, "%s does not take keyword arguments",                      funcname); | 
