diff options
Diffstat (limited to 'Python/getargs.c')
-rw-r--r-- | Python/getargs.c | 2447 |
1 files changed, 774 insertions, 1673 deletions
diff --git a/Python/getargs.c b/Python/getargs.c index 351889f..12ee248 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -2,10 +2,8 @@ /* New getargs implementation */ #include "Python.h" -#include "pycore_tupleobject.h" #include <ctype.h> -#include <float.h> #ifdef __cplusplus @@ -20,79 +18,37 @@ int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, 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_Parse_SizeT(PyObject *, char *, ...); +PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, 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_VaParse_SizeT(PyObject *, 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 void seterror(int, const char *, int *, const char *, const char *); +static char *convertitem(PyObject *, const char **, va_list *, int, int *, + char *, size_t, PyObject **); +static char *converttuple(PyObject *, const char **, va_list *, int, + int *, char *, size_t, int, PyObject **); +static char *convertsimple(PyObject *, const char **, va_list *, int, char *, + size_t, PyObject **); +static Py_ssize_t convertbuffer(PyObject *, void **p, char **); +static int getbuffer(PyObject *, Py_buffer *, 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); +static char *skipitem(const char **, va_list *, int); int PyArg_Parse(PyObject *args, const char *format, ...) @@ -106,8 +62,8 @@ PyArg_Parse(PyObject *args, const char *format, ...) return retval; } -PyAPI_FUNC(int) -_PyArg_Parse_SizeT(PyObject *args, const char *format, ...) +int +_PyArg_Parse_SizeT(PyObject *args, char *format, ...) { int retval; va_list va; @@ -131,39 +87,14 @@ PyArg_ParseTuple(PyObject *args, const char *format, ...) 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, ...) +_PyArg_ParseTuple_SizeT(PyObject *args, 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); + retval = vgetargs1(args, format, &va, FLAG_SIZE_T); va_end(va); return retval; } @@ -173,87 +104,113 @@ int PyArg_VaParse(PyObject *args, const char *format, va_list va) { va_list lva; - int retval; - va_copy(lva, va); +#ifdef VA_LIST_IS_ARRAY + memcpy(lva, va, sizeof(va_list)); +#else +#ifdef __va_copy + __va_copy(lva, va); +#else + lva = va; +#endif +#endif - retval = vgetargs1(args, format, &lva, 0); - va_end(lva); - return retval; + return vgetargs1(args, format, &lva, 0); } -PyAPI_FUNC(int) -_PyArg_VaParse_SizeT(PyObject *args, const char *format, va_list va) +int +_PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) { va_list lva; - int retval; - va_copy(lva, va); +#ifdef VA_LIST_IS_ARRAY + memcpy(lva, va, sizeof(va_list)); +#else +#ifdef __va_copy + __va_copy(lva, va); +#else + lva = va; +#endif +#endif - retval = vgetargs1(args, format, &lva, FLAG_SIZE_T); - va_end(lva); - return retval; + return vgetargs1(args, format, &lva, FLAG_SIZE_T); } /* Handle cleanup of allocated memory in case of exception */ -static int -cleanup_ptr(PyObject *self, void *ptr) +#define GETARGS_CAPSULE_NAME_CLEANUP_PTR "getargs.cleanup_ptr" +#define GETARGS_CAPSULE_NAME_CLEANUP_BUFFER "getargs.cleanup_buffer" + +static void +cleanup_ptr(PyObject *self) { + void *ptr = PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_PTR); if (ptr) { - PyMem_FREE(ptr); + PyMem_FREE(ptr); } - return 0; } -static int -cleanup_buffer(PyObject *self, void *ptr) +static void +cleanup_buffer(PyObject *self) { - Py_buffer *buf = (Py_buffer *)ptr; - if (buf) { - PyBuffer_Release(buf); + Py_buffer *ptr = (Py_buffer *)PyCapsule_GetPointer(self, GETARGS_CAPSULE_NAME_CLEANUP_BUFFER); + if (ptr) { + PyBuffer_Release(ptr); } - return 0; } static int -addcleanup(void *ptr, freelist_t *freelist, destr_t destructor) +addcleanup(void *ptr, PyObject **freelist, PyCapsule_Destructor destr) { - int index; - - index = freelist->first_available; - freelist->first_available += 1; + PyObject *cobj; + const char *name; - freelist->entries[index].item = ptr; - freelist->entries[index].destructor = destructor; + if (!*freelist) { + *freelist = PyList_New(0); + if (!*freelist) { + destr(ptr); + return -1; + } + } + if (destr == cleanup_ptr) { + name = GETARGS_CAPSULE_NAME_CLEANUP_PTR; + } else if (destr == cleanup_buffer) { + name = GETARGS_CAPSULE_NAME_CLEANUP_BUFFER; + } else { + return -1; + } + cobj = PyCapsule_New(ptr, name, destr); + if (!cobj) { + destr(ptr); + return -1; + } + if (PyList_Append(*freelist, cobj)) { + Py_DECREF(cobj); + return -1; + } + Py_DECREF(cobj); return 0; } static int -cleanreturn(int retval, freelist_t *freelist) +cleanreturn(int retval, PyObject *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); + if (freelist && retval != 0) { + /* We were successful, reset the destructors so that they + don't get called. */ + Py_ssize_t len = PyList_GET_SIZE(freelist), i; + for (i = 0; i < len; i++) + PyCapsule_SetDestructor(PyList_GET_ITEM(freelist, i), NULL); + } + Py_XDECREF(freelist); 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) +vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) { char msgbuf[256]; int levels[32]; @@ -264,18 +221,12 @@ vgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, int level = 0; int endfmt = 0; const char *formatsave = format; - Py_ssize_t i; - const char *msg; + Py_ssize_t i, len; + char *msg; + PyObject *freelist = NULL; 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) { @@ -306,15 +257,15 @@ vgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, message = format; endfmt = 1; break; - case '|': - if (level == 0) - min = max; - break; default: if (level == 0) { - if (Py_ISALPHA(c)) + if (c == 'O') + max++; + else if (isalpha(Py_CHARMASK(c))) { if (c != 'e') /* skip encoded */ max++; + } else if (c == '|') + min = max; } break; } @@ -328,115 +279,93 @@ vgetargs1_impl(PyObject *compat_args, PyObject *const *stack, Py_ssize_t nargs, 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) + if (args == NULL) return 1; - PyErr_Format(PyExc_TypeError, - "%.200s%s takes no arguments", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); - return cleanreturn(0, &freelist); + PyOS_snprintf(msgbuf, sizeof(msgbuf), + "%.200s%s takes no arguments", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()"); + PyErr_SetString(PyExc_TypeError, msgbuf); + return 0; } 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); + if (args == NULL) { + PyOS_snprintf(msgbuf, sizeof(msgbuf), + "%.200s%s takes at least one argument", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()"); + PyErr_SetString(PyExc_TypeError, msgbuf); + return 0; } - msg = convertitem(compat_args, &format, p_va, flags, levels, + msg = convertitem(args, &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg == NULL) - return cleanreturn(1, &freelist); + return cleanreturn(1, freelist); seterror(levels[0], msg, levels+1, fname, message); - return cleanreturn(0, &freelist); + return cleanreturn(0, freelist); } else { PyErr_SetString(PyExc_SystemError, "old style getargs format uses new features"); - return cleanreturn(0, &freelist); + return 0; } } - 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", - nargs); - else - PyErr_SetString(PyExc_TypeError, message); - return cleanreturn(0, &freelist); + if (!PyTuple_Check(args)) { + PyErr_SetString(PyExc_SystemError, + "new style getargs format but argument is not a tuple"); + return 0; } - for (i = 0; i < nargs; i++) { + len = PyTuple_GET_SIZE(args); + + if (len < min || max < len) { + if (message == NULL) { + PyOS_snprintf(msgbuf, sizeof(msgbuf), + "%.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)); + message = msgbuf; + } + PyErr_SetString(PyExc_TypeError, message); + return 0; + } + + for (i = 0; i < len; i++) { if (*format == '|') format++; - msg = convertitem(stack[i], &format, p_va, + msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg) { seterror(i+1, msg, levels, fname, message); - return cleanreturn(0, &freelist); + return cleanreturn(0, freelist); } } - if (*format != '\0' && !Py_ISALPHA(*format) && + if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) && *format != '(' && *format != '|' && *format != ':' && *format != ';') { PyErr_Format(PyExc_SystemError, "bad format string: %.200s", formatsave); - return cleanreturn(0, &freelist); + return cleanreturn(0, freelist); } - return cleanreturn(1, &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, +seterror(int iarg, const char *msg, int *levels, const char *fname, const char *message) { char buf[512]; @@ -452,10 +381,10 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, } if (iarg != 0) { PyOS_snprintf(p, sizeof(buf) - (p - buf), - "argument %" PY_FORMAT_SIZE_T "d", iarg); + "argument %d", iarg); i = 0; p += strlen(p); - while (i < 32 && levels[i] > 0 && (int)(p-buf) < 220) { + while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { PyOS_snprintf(p, sizeof(buf) - (p - buf), ", item %d", levels[i]-1); p += strlen(p); @@ -469,12 +398,7 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, 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); - } + PyErr_SetString(PyExc_TypeError, message); } @@ -496,16 +420,15 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, and msgbuf is returned. */ -static const char * +static 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) + PyObject **freelist) { int level = 0; int n = 0; const char *format = *p_format; int i; - Py_ssize_t len; for (;;) { int c = *format++; @@ -521,11 +444,11 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } else if (c == ':' || c == ';' || c == '\0') break; - else if (level == 0 && Py_ISALPHA(c)) + else if (level == 0 && isalpha(Py_CHARMASK(c))) n++; } - if (!PySequence_Check(arg) || PyBytes_Check(arg)) { + if (!PySequence_Check(arg) || PyString_Check(arg)) { levels[0] = 0; PyOS_snprintf(msgbuf, bufsize, toplevel ? "expected %d arguments, not %.50s" : @@ -535,28 +458,18 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return msgbuf; } - len = PySequence_Size(arg); - if (len != n) { + if ((i = PySequence_Size(arg)) != 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); - } + PyOS_snprintf(msgbuf, bufsize, + toplevel ? "expected %d arguments, not %d" : + "must be sequence of length %d, not %d", + n, i); return msgbuf; } format = *p_format; for (i = 0; i < n; i++) { - const char *msg; + char *msg; PyObject *item; item = PySequence_GetItem(arg, i); if (item == NULL) { @@ -583,11 +496,11 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, /* Convert a single item. */ -static const char * +static char * convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, - int *levels, char *msgbuf, size_t bufsize, freelist_t *freelist) + int *levels, char *msgbuf, size_t bufsize, PyObject **freelist) { - const char *msg; + char *msg; const char *format = *p_format; if (*format == '(' /* ')' */) { @@ -610,21 +523,12 @@ convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, -/* Format an error message generated by convertsimple(). - displayname must be UTF-8 encoded. -*/ +#define UNICODE_DEFAULT_ENCODING(arg) \ + _PyUnicode_AsDefaultEncodedString(arg, NULL) -void -_PyArg_BadArgument(const char *fname, const char *displayname, - const char *expected, PyObject *arg) -{ - PyErr_Format(PyExc_TypeError, - "%.200s() %.200s must be %.50s, not %.50s", - fname, displayname, expected, - arg == Py_None ? "None" : arg->ob_type->tp_name); -} +/* Format an error message generated by convertsimple(). */ -static const char * +static char * converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) { assert(expected != NULL); @@ -632,6 +536,8 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) if (expected[0] == '(') { PyOS_snprintf(msgbuf, bufsize, "%.100s", expected); + strncpy(msgbuf, expected, bufsize); + msgbuf[bufsize-1] = '\0'; } else { PyOS_snprintf(msgbuf, bufsize, @@ -643,22 +549,44 @@ converterr(const char *expected, PyObject *arg, char *msgbuf, size_t bufsize) #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. */ +/* explicitly check for float arguments when integers are expected. For now + * signal a warning. Returns true if an exception was raised. */ +static int +float_argument_warning(PyObject *arg) +{ + if (PyFloat_Check(arg) && + PyErr_Warn(PyExc_DeprecationWarning, + "integer argument expected, got float" )) + return 1; + else + return 0; +} + +/* explicitly check for float arguments when integers are expected. Raises + TypeError and returns true for float arguments. */ static int float_argument_error(PyObject *arg) { if (PyFloat_Check(arg)) { PyErr_SetString(PyExc_TypeError, - "integer argument expected, got float" ); + "integer argument expected, got float"); return 1; } else return 0; } +#ifdef Py_USING_UNICODE +static size_t +_ustrlen(Py_UNICODE *u) +{ + size_t i = 0; + Py_UNICODE *v = u; + while (*v != 0) { i++; v++; } + return i; +} +#endif + /* 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>". @@ -668,20 +596,14 @@ float_argument_error(PyObject *arg) When you add new format codes, please don't forget poor skipitem() below. */ -static const char * +static char * convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, - char *msgbuf, size_t bufsize, freelist_t *freelist) + char *msgbuf, size_t bufsize, PyObject **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)) { \ - return NULL; \ - } \ - q=va_arg(*p_va, int*); \ - } + else q=va_arg(*p_va, int*); #define STORE_SIZE(s) \ if (flags & FLAG_SIZE_T) \ *q2=s; \ @@ -691,14 +613,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, "size does not fit in an int"); \ return converterr("", arg, msgbuf, bufsize); \ } \ - *q = (int)s; \ + *q=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; +#ifdef Py_USING_UNICODE + PyObject *uarg; +#endif switch (c) { @@ -706,19 +629,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *p = va_arg(*p_va, char *); long ival; if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLong(arg); + return converterr("integer<b>", arg, msgbuf, bufsize); + ival = PyInt_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<b>", arg, msgbuf, bufsize); else if (ival < 0) { PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is less than minimum"); - RETURN_ERR_OCCURRED; + "unsigned byte integer is less than minimum"); + return converterr("integer<b>", arg, msgbuf, bufsize); } else if (ival > UCHAR_MAX) { PyErr_SetString(PyExc_OverflowError, - "unsigned byte integer is greater than maximum"); - RETURN_ERR_OCCURRED; + "unsigned byte integer is greater than maximum"); + return converterr("integer<b>", arg, msgbuf, bufsize); } else *p = (unsigned char) ival; @@ -730,10 +653,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char *p = va_arg(*p_va, char *); long ival; if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsUnsignedLongMask(arg); + return converterr("integer<B>", arg, msgbuf, bufsize); + ival = PyInt_AsUnsignedLongMask(arg); if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<B>", arg, msgbuf, bufsize); else *p = (unsigned char) ival; break; @@ -743,19 +666,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, short *p = va_arg(*p_va, short *); long ival; if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLong(arg); + return converterr("integer<h>", arg, msgbuf, bufsize); + ival = PyInt_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<h>", arg, msgbuf, bufsize); else if (ival < SHRT_MIN) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is less than minimum"); - RETURN_ERR_OCCURRED; + "signed short integer is less than minimum"); + return converterr("integer<h>", arg, msgbuf, bufsize); } else if (ival > SHRT_MAX) { PyErr_SetString(PyExc_OverflowError, - "signed short integer is greater than maximum"); - RETURN_ERR_OCCURRED; + "signed short integer is greater than maximum"); + return converterr("integer<h>", arg, msgbuf, bufsize); } else *p = (short) ival; @@ -767,10 +690,10 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, unsigned short *p = va_arg(*p_va, unsigned short *); long ival; if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsUnsignedLongMask(arg); + return converterr("integer<H>", arg, msgbuf, bufsize); + ival = PyInt_AsUnsignedLongMask(arg); if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<H>", arg, msgbuf, bufsize); else *p = (unsigned short) ival; break; @@ -780,19 +703,19 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *p = va_arg(*p_va, int *); long ival; if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - ival = PyLong_AsLong(arg); + return converterr("integer<i>", arg, msgbuf, bufsize); + ival = PyInt_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<i>", arg, msgbuf, bufsize); else if (ival > INT_MAX) { PyErr_SetString(PyExc_OverflowError, - "signed integer is greater than maximum"); - RETURN_ERR_OCCURRED; + "signed integer is greater than maximum"); + return converterr("integer<i>", arg, msgbuf, bufsize); } else if (ival < INT_MIN) { PyErr_SetString(PyExc_OverflowError, - "signed integer is less than minimum"); - RETURN_ERR_OCCURRED; + "signed integer is less than minimum"); + return converterr("integer<i>", arg, msgbuf, bufsize); } else *p = ival; @@ -804,40 +727,38 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, 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); + return converterr("integer<I>", arg, msgbuf, bufsize); + ival = (unsigned int)PyInt_AsUnsignedLongMask(arg); if (ival == (unsigned int)-1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<I>", arg, msgbuf, bufsize); else *p = ival; break; } case 'n': /* Py_ssize_t */ +#if SIZEOF_SIZE_T != SIZEOF_LONG { - PyObject *iobj; Py_ssize_t *p = va_arg(*p_va, Py_ssize_t *); - Py_ssize_t ival = -1; + Py_ssize_t ival; if (float_argument_error(arg)) - RETURN_ERR_OCCURRED; - iobj = PyNumber_Index(arg); - if (iobj != NULL) { - ival = PyLong_AsSsize_t(iobj); - Py_DECREF(iobj); - } + return converterr("integer<n>", arg, msgbuf, bufsize); + ival = PyInt_AsSsize_t(arg); if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<n>", arg, msgbuf, bufsize); *p = ival; break; } +#endif + /* Fall through from 'n' to 'l' if Py_ssize_t is int */ 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); + return converterr("integer<l>", arg, msgbuf, bufsize); + ival = PyInt_AsLong(arg); if (ival == -1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + return converterr("integer<l>", arg, msgbuf, bufsize); else *p = ival; break; @@ -846,43 +767,50 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'k': { /* long sized bitfield */ unsigned long *p = va_arg(*p_va, unsigned long *); unsigned long ival; - if (PyLong_Check(arg)) + if (PyInt_Check(arg)) + ival = PyInt_AsUnsignedLongMask(arg); + else if (PyLong_Check(arg)) ival = PyLong_AsUnsignedLongMask(arg); else - return converterr("int", arg, msgbuf, bufsize); + return converterr("an integer", 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; +#ifdef HAVE_LONG_LONG + case 'L': {/* PY_LONG_LONG */ + PY_LONG_LONG *p = va_arg( *p_va, PY_LONG_LONG * ); + PY_LONG_LONG ival; + if (float_argument_warning(arg)) + return converterr("long<L>", arg, msgbuf, bufsize); ival = PyLong_AsLongLong(arg); - if (ival == (long long)-1 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; - else + if (ival == (PY_LONG_LONG)-1 && PyErr_Occurred() ) { + return converterr("long<L>", arg, msgbuf, bufsize); + } 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)) + unsigned PY_LONG_LONG *p = va_arg(*p_va, unsigned PY_LONG_LONG *); + unsigned PY_LONG_LONG ival; + if (PyInt_Check(arg)) + ival = PyInt_AsUnsignedLongMask(arg); + else if (PyLong_Check(arg)) ival = PyLong_AsUnsignedLongLongMask(arg); else - return converterr("int", arg, msgbuf, bufsize); + return converterr("an integer", arg, msgbuf, bufsize); *p = ival; break; } +#endif case 'f': {/* float */ float *p = va_arg(*p_va, float *); double dval = PyFloat_AsDouble(arg); - if (dval == -1.0 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + if (PyErr_Occurred()) + return converterr("float<f>", arg, msgbuf, bufsize); else *p = (float) dval; break; @@ -891,120 +819,139 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, case 'd': {/* double */ double *p = va_arg(*p_va, double *); double dval = PyFloat_AsDouble(arg); - if (dval == -1.0 && PyErr_Occurred()) - RETURN_ERR_OCCURRED; + if (PyErr_Occurred()) + return converterr("float<d>", arg, msgbuf, bufsize); else *p = dval; break; } +#ifndef WITHOUT_COMPLEX 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; + return converterr("complex<D>", arg, msgbuf, bufsize); else *p = cval; break; } +#endif /* WITHOUT_COMPLEX */ 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]; + if (PyString_Check(arg) && PyString_Size(arg) == 1) + *p = PyString_AS_STRING(arg)[0]; else - return converterr("a byte string of length 1", arg, msgbuf, bufsize); + return converterr("char", arg, msgbuf, bufsize); break; } - case 'C': {/* unicode char */ - int *p = va_arg(*p_va, int *); - int kind; - 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; + case 's': {/* string */ if (*format == '*') { - if (getbuffer(arg, (Py_buffer*)p, &buf) < 0) - return converterr(buf, arg, msgbuf, bufsize); - format++; + Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); + + if (PyString_Check(arg)) { + PyBuffer_FillInfo(p, arg, + PyString_AS_STRING(arg), PyString_GET_SIZE(arg), + 1, 0); + } +#ifdef Py_USING_UNICODE + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + PyBuffer_FillInfo(p, arg, + PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg), + 1, 0); + } +#endif + else { /* any buffer-like object */ + 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); } - break; - } - count = convertbuffer(arg, (const void **)p, &buf); - if (count < 0) - return converterr(buf, arg, msgbuf, bufsize); - if (*format == '#') { + format++; + } else if (*format == '#') { + void **p = (void **)va_arg(*p_va, char **); FETCH_SIZE; - STORE_SIZE(count); + + if (PyString_Check(arg)) { + *p = PyString_AS_STRING(arg); + STORE_SIZE(PyString_GET_SIZE(arg)); + } +#ifdef Py_USING_UNICODE + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyString_AS_STRING(uarg); + STORE_SIZE(PyString_GET_SIZE(uarg)); + } +#endif + else { /* any buffer-like object */ + char *buf; + Py_ssize_t count = convertbuffer(arg, p, &buf); + if (count < 0) + return converterr(buf, arg, msgbuf, bufsize); + STORE_SIZE(count); + } format++; } else { - if (strlen(*p) != (size_t)count) { - PyErr_SetString(PyExc_ValueError, "embedded null byte"); - RETURN_ERR_OCCURRED; + char **p = va_arg(*p_va, char **); + + if (PyString_Check(arg)) + *p = PyString_AS_STRING(arg); +#ifdef Py_USING_UNICODE + else if (PyUnicode_Check(arg)) { + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) + return converterr(CONV_UNICODE, + arg, msgbuf, bufsize); + *p = PyString_AS_STRING(uarg); } +#endif + else + return converterr("string", arg, msgbuf, bufsize); + if ((Py_ssize_t)strlen(*p) != PyString_Size(arg)) + return converterr("string without null bytes", + arg, msgbuf, bufsize); } break; } - case 's': /* text string or bytes-like object */ - case 'z': /* text string, bytes-like object or None */ - { + case 'z': {/* string, may be NULL (None) */ if (*format == '*') { - /* "s*" or "z*" */ Py_buffer *p = (Py_buffer *)va_arg(*p_va, Py_buffer *); - if (c == 'z' && arg == Py_None) + if (arg == Py_None) PyBuffer_FillInfo(p, NULL, NULL, 0, 1, 0); + else if (PyString_Check(arg)) { + PyBuffer_FillInfo(p, arg, + PyString_AS_STRING(arg), PyString_GET_SIZE(arg), + 1, 0); + } +#ifdef Py_USING_UNICODE else if (PyUnicode_Check(arg)) { - Py_ssize_t len; - sarg = PyUnicode_AsUTF8AndSize(arg, &len); - if (sarg == NULL) + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) return converterr(CONV_UNICODE, arg, msgbuf, bufsize); - PyBuffer_FillInfo(p, arg, (void *)sarg, len, 1, 0); + PyBuffer_FillInfo(p, arg, + PyString_AS_STRING(uarg), PyString_GET_SIZE(uarg), + 1, 0); } - else { /* any bytes-like object */ - const char *buf; +#endif + else { /* any buffer-like object */ + char *buf; if (getbuffer(arg, p, &buf) < 0) return converterr(buf, arg, msgbuf, bufsize); } @@ -1014,27 +961,30 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, 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 **); + } else if (*format == '#') { /* any buffer-like object */ + void **p = (void **)va_arg(*p_va, char **); FETCH_SIZE; - if (c == 'z' && arg == Py_None) { - *p = NULL; + if (arg == Py_None) { + *p = 0; STORE_SIZE(0); } + else if (PyString_Check(arg)) { + *p = PyString_AS_STRING(arg); + STORE_SIZE(PyString_GET_SIZE(arg)); + } +#ifdef Py_USING_UNICODE else if (PyUnicode_Check(arg)) { - Py_ssize_t len; - sarg = PyUnicode_AsUTF8AndSize(arg, &len); - if (sarg == NULL) + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == NULL) return converterr(CONV_UNICODE, arg, msgbuf, bufsize); - *p = sarg; - STORE_SIZE(len); + *p = PyString_AS_STRING(uarg); + STORE_SIZE(PyString_GET_SIZE(uarg)); } - else { /* read-only bytes-like object */ - /* XXX Really? */ - const char *buf; +#endif + else { /* any buffer-like object */ + char *buf; Py_ssize_t count = convertbuffer(arg, p, &buf); if (count < 0) return converterr(buf, arg, msgbuf, bufsize); @@ -1042,71 +992,39 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } format++; } else { - /* "s" or "z" */ - const char **p = va_arg(*p_va, const char **); - Py_ssize_t len; - sarg = NULL; + char **p = va_arg(*p_va, char **); - if (c == 'z' && arg == Py_None) - *p = NULL; + if (arg == Py_None) + *p = 0; + else if (PyString_Check(arg)) + *p = PyString_AS_STRING(arg); +#ifdef Py_USING_UNICODE else if (PyUnicode_Check(arg)) { - sarg = PyUnicode_AsUTF8AndSize(arg, &len); - if (sarg == NULL) + uarg = UNICODE_DEFAULT_ENCODING(arg); + if (uarg == 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 */ - { - 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); + *p = PyString_AS_STRING(uarg); } +#endif else - return converterr(c == 'Z' ? "str or None" : "str", + return converterr("string or None", 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; + if (*format == '#') { + FETCH_SIZE; + assert(0); /* XXX redundant with if-case */ + if (arg == Py_None) { + STORE_SIZE(0); + } else { + STORE_SIZE(PyString_Size(arg)); } - } else - return converterr(c == 'Z' ? "str or None" : "str", - arg, msgbuf, bufsize); + format++; + } + else if (*p != NULL && + (Py_ssize_t)strlen(*p) != PyString_Size(arg)) + return converterr( + "string without null bytes or None", + arg, msgbuf, bufsize); } break; } @@ -1115,14 +1033,15 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, char **buffer; const char *encoding; PyObject *s; - int recode_strings; Py_ssize_t size; - const char *ptr; + int recode_strings; /* Get 'e' parameter: the encoding name */ encoding = (const char *)va_arg(*p_va, const char *); +#ifdef Py_USING_UNICODE if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); +#endif /* Get output buffer parameter: 's' (recode all objects via Unicode) or @@ -1143,38 +1062,40 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, arg, msgbuf, bufsize); /* Encode object */ - if (!recode_strings && - (PyBytes_Check(arg) || PyByteArray_Check(arg))) { + if (!recode_strings && PyString_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)) { + else { +#ifdef Py_USING_UNICODE + PyObject *u; + + /* Convert object to Unicode */ + u = PyUnicode_FromObject(arg); + if (u == NULL) + return converterr( + "string or unicode or text buffer", + arg, msgbuf, bufsize); + /* Encode object; use default error handling */ - s = PyUnicode_AsEncodedString(arg, + s = PyUnicode_AsEncodedString(u, encoding, NULL); + Py_DECREF(u); 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); + if (!PyString_Check(s)) { + Py_DECREF(s); + return converterr( + "(encoder failed to return a string)", + arg, msgbuf, bufsize); + } +#else + return converterr("string<e>", arg, msgbuf, bufsize); +#endif } + size = PyString_GET_SIZE(s); /* Write output; output is guaranteed to be 0-terminated */ if (*format == '#') { @@ -1199,19 +1120,7 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, trailing 0-byte */ - 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)) - { - Py_DECREF(s); - return NULL; - } - q = va_arg(*p_va, int*); - } + FETCH_SIZE; format++; if (q == NULL && q2 == NULL) { @@ -1224,8 +1133,9 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); - PyErr_NoMemory(); - RETURN_ERR_OCCURRED; + return converterr( + "(memory error)", + arg, msgbuf, bufsize); } if (addcleanup(*buffer, freelist, cleanup_ptr)) { Py_DECREF(s); @@ -1236,14 +1146,16 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, } else { if (size + 1 > BUFFER_LEN) { Py_DECREF(s); - PyErr_Format(PyExc_ValueError, + PyErr_Format(PyExc_TypeError, "encoded string too long " "(%zd, maximum length %zd)", (Py_ssize_t)size, (Py_ssize_t)(BUFFER_LEN-1)); - RETURN_ERR_OCCURRED; + return ""; } } - memcpy(*buffer, ptr, size+1); + memcpy(*buffer, + PyString_AS_STRING(s), + size + 1); if (flags & FLAG_SIZE_T) { *q2 = size; @@ -1271,7 +1183,8 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, PyMem_Free()ing it after usage */ - if ((Py_ssize_t)strlen(ptr) != size) { + if ((Py_ssize_t)strlen(PyString_AS_STRING(s)) + != size) { Py_DECREF(s); return converterr( "encoded string without null bytes", @@ -1280,49 +1193,72 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *buffer = PyMem_NEW(char, size + 1); if (*buffer == NULL) { Py_DECREF(s); - PyErr_NoMemory(); - RETURN_ERR_OCCURRED; + return converterr("(memory error)", + arg, msgbuf, bufsize); } if (addcleanup(*buffer, freelist, cleanup_ptr)) { Py_DECREF(s); return converterr("(cleanup problem)", arg, msgbuf, bufsize); } - memcpy(*buffer, ptr, size+1); + memcpy(*buffer, + PyString_AS_STRING(s), + 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); +#ifdef Py_USING_UNICODE + case 'u': {/* raw unicode buffer (Py_UNICODE *) */ + if (*format == '#') { /* any buffer-like object */ + void **p = (void **)va_arg(*p_va, char **); + FETCH_SIZE; + if (PyUnicode_Check(arg)) { + *p = PyUnicode_AS_UNICODE(arg); + STORE_SIZE(PyUnicode_GET_SIZE(arg)); + } + else { + return converterr("cannot convert raw buffers", + arg, msgbuf, bufsize); + } + format++; + } else { + Py_UNICODE **p = va_arg(*p_va, Py_UNICODE **); + if (PyUnicode_Check(arg)) { + *p = PyUnicode_AS_UNICODE(arg); + if (_ustrlen(*p) != (size_t)PyUnicode_GET_SIZE(arg)) { + return converterr( + "unicode without null characters", + arg, msgbuf, bufsize); + } + } + else + return converterr("unicode", arg, msgbuf, bufsize); + } break; } +#endif - case 'Y': { /* PyByteArray object */ + case 'S': { /* string object */ PyObject **p = va_arg(*p_va, PyObject **); - if (PyByteArray_Check(arg)) + if (PyString_Check(arg)) *p = arg; else - return converterr("bytearray", arg, msgbuf, bufsize); + return converterr("string", arg, msgbuf, bufsize); break; } - case 'U': { /* PyUnicode object */ +#ifdef Py_USING_UNICODE + case 'U': { /* Unicode object */ PyObject **p = va_arg(*p_va, PyObject **); - if (PyUnicode_Check(arg)) { - if (PyUnicode_READY(arg) == -1) - RETURN_ERR_OCCURRED; + if (PyUnicode_Check(arg)) *p = arg; - } else - return converterr("str", arg, msgbuf, bufsize); + return converterr("unicode", arg, msgbuf, bufsize); break; } +#endif case 'O': { /* object */ PyTypeObject *type; @@ -1337,19 +1273,25 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return converterr(type->tp_name, arg, msgbuf, bufsize); } + else if (*format == '?') { + inquiry pred = va_arg(*p_va, inquiry); + p = va_arg(*p_va, PyObject **); + format++; + if ((*pred)(arg)) + *p = arg; + else + return converterr("(unspecified)", + 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))) + if (! (*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 **); @@ -1358,31 +1300,92 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, break; } - - case 'w': { /* "w*": memory buffer, read-write access */ + case 'w': { /* memory buffer, read-write access */ void **p = va_arg(*p_va, void **); + void *res; + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + Py_ssize_t count; - if (*format != '*') - return converterr( - "(invalid use of 'w' format character)", - arg, msgbuf, bufsize); - format++; + if (pb && pb->bf_releasebuffer && *format != '*') + /* Buffer must be released, yet caller does not use + the Py_buffer protocol. */ + return converterr("pinned buffer", arg, msgbuf, bufsize); - /* 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", + if (pb && pb->bf_getbuffer && *format == '*') { + /* Caller is interested in Py_buffer, and the object + supports it directly. */ + format++; + if (pb->bf_getbuffer(arg, (Py_buffer*)p, PyBUF_WRITABLE) < 0) { + PyErr_Clear(); + return converterr("read-write buffer", arg, msgbuf, bufsize); + } + if (addcleanup(p, freelist, cleanup_buffer)) { + return converterr( + "(cleanup problem)", + arg, msgbuf, bufsize); + } + if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) + return converterr("contiguous buffer", arg, msgbuf, bufsize); + break; + } + + if (pb == NULL || + pb->bf_getwritebuffer == NULL || + pb->bf_getsegcount == NULL) + return converterr("read-write buffer", arg, msgbuf, bufsize); + if ((*pb->bf_getsegcount)(arg, NULL) != 1) + return converterr("single-segment read-write buffer", arg, msgbuf, bufsize); + if ((count = pb->bf_getwritebuffer(arg, 0, &res)) < 0) + return converterr("(unspecified)", arg, msgbuf, bufsize); + if (*format == '*') { + PyBuffer_FillInfo((Py_buffer*)p, arg, res, count, 1, 0); + format++; } - if (!PyBuffer_IsContiguous((Py_buffer*)p, 'C')) { - PyBuffer_Release((Py_buffer*)p); - return converterr("contiguous buffer", arg, msgbuf, bufsize); + else { + *p = res; + if (*format == '#') { + FETCH_SIZE; + STORE_SIZE(count); + format++; + } } - if (addcleanup(p, freelist, cleanup_buffer)) { + break; + } + + case 't': { /* 8-bit character buffer, read-only access */ + char **p = va_arg(*p_va, char **); + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + Py_ssize_t count; + + if (*format++ != '#') + return converterr( + "invalid use of 't' format character", + arg, msgbuf, bufsize); + if (!PyType_HasFeature(arg->ob_type, + Py_TPFLAGS_HAVE_GETCHARBUFFER) || + pb == NULL || pb->bf_getcharbuffer == NULL || + pb->bf_getsegcount == NULL) + return converterr( + "string or read-only character buffer", + arg, msgbuf, bufsize); + + if (pb->bf_getsegcount(arg, NULL) != 1) return converterr( - "(cleanup problem)", + "string or single-segment read-only buffer", arg, msgbuf, bufsize); + + if (pb->bf_releasebuffer) + return converterr( + "string or pinned buffer", + arg, msgbuf, bufsize); + + count = pb->bf_getcharbuffer(arg, 0, p); + if (count < 0) + return converterr("(unspecified)", arg, msgbuf, bufsize); + { + FETCH_SIZE; + STORE_SIZE(count); } break; } @@ -1394,47 +1397,58 @@ convertsimple(PyObject *arg, const char **p_format, va_list *p_va, int flags, *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) +convertbuffer(PyObject *arg, void **p, char **errmsg) { - PyBufferProcs *pb = Py_TYPE(arg)->tp_as_buffer; + PyBufferProcs *pb = arg->ob_type->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"; + if (pb == NULL || + pb->bf_getreadbuffer == NULL || + pb->bf_getsegcount == NULL || + pb->bf_releasebuffer != NULL) { + *errmsg = "string or read-only buffer"; return -1; } - - if (getbuffer(arg, &view, errmsg) < 0) + if ((*pb->bf_getsegcount)(arg, NULL) != 1) { + *errmsg = "string or single-segment read-only buffer"; return -1; - count = view.len; - *p = view.buf; - PyBuffer_Release(&view); + } + if ((count = (*pb->bf_getreadbuffer)(arg, 0, p)) < 0) { + *errmsg = "(unspecified)"; + } return count; } static int -getbuffer(PyObject *arg, Py_buffer *view, const char **errmsg) +getbuffer(PyObject *arg, Py_buffer *view, char **errmsg) { - if (PyObject_GetBuffer(arg, view, PyBUF_SIMPLE) != 0) { - *errmsg = "bytes-like object"; + void *buf; + Py_ssize_t count; + PyBufferProcs *pb = arg->ob_type->tp_as_buffer; + if (pb == NULL) { + *errmsg = "string or buffer"; return -1; } - if (!PyBuffer_IsContiguous(view, 'C')) { - PyBuffer_Release(view); - *errmsg = "contiguous buffer"; - return -1; + if (pb->bf_getbuffer) { + if (pb->bf_getbuffer(arg, view, 0) < 0) { + *errmsg = "convertible to a buffer"; + return -1; + } + if (!PyBuffer_IsContiguous(view, 'C')) { + *errmsg = "contiguous buffer"; + return -1; + } + return 0; } + + count = convertbuffer(arg, &buf, errmsg); + if (count < 0) { + *errmsg = "convertible to a buffer"; + return count; + } + PyBuffer_FillInfo(view, arg, buf, count, 1, 0); return 0; } @@ -1466,7 +1480,7 @@ PyArg_ParseTupleAndKeywords(PyObject *args, return retval; } -PyAPI_FUNC(int) +int _PyArg_ParseTupleAndKeywords_SizeT(PyObject *args, PyObject *keywords, const char *format, @@ -1510,14 +1524,21 @@ PyArg_VaParseTupleAndKeywords(PyObject *args, return 0; } - va_copy(lva, va); +#ifdef VA_LIST_IS_ARRAY + memcpy(lva, va, sizeof(va_list)); +#else +#ifdef __va_copy + __va_copy(lva, va); +#else + lva = va; +#endif +#endif retval = vgetargskeywords(args, keywords, format, kwlist, &lva, 0); - va_end(lva); return retval; } -PyAPI_FUNC(int) +int _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, PyObject *keywords, const char *format, @@ -1535,134 +1556,36 @@ _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *args, return 0; } - va_copy(lva, va); +#ifdef VA_LIST_IS_ARRAY + memcpy(lva, va, sizeof(va_list)); +#else +#ifdef __va_copy + __va_copy(lva, va); +#else + lva = va; +#endif +#endif 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; -} - -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; -} - -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; -} - -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; -} - - -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; } -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, +vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, char **kwlist, va_list *p_va, int flags) { char msgbuf[512]; int levels[32]; - const char *fname, *msg, *custom_msg; + const char *fname, *msg, *custom_msg, *keyword; 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; + int i, len, nargs, nkeywords; + PyObject *freelist = NULL, *current_arg; assert(args != NULL && PyTuple_Check(args)); - assert(kwargs == NULL || PyDict_Check(kwargs)); + assert(keywords == NULL || PyDict_Check(keywords)); assert(format != NULL); assert(kwlist != NULL); assert(p_va != NULL); @@ -1679,861 +1602,130 @@ vgetargskeywords(PyObject *args, PyObject *kwargs, const char *format, 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; - } + for (len=0; kwlist[len]; len++) + continue; 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)", + nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); + if (nargs + nkeywords > len) { + PyErr_Format(PyExc_TypeError, "%s%s takes at most %d " + "argument%s (%d given)", (fname == NULL) ? "function" : fname, (fname == NULL) ? "" : "()", len, - (nargs == 0) ? "keyword " : "", (len == 1) ? "" : "s", - nargs + nkwargs); - return cleanreturn(0, &freelist); + nargs + nkeywords); + return 0; } /* convert tuple args and keyword args in same loop, using kwlist to drive process */ for (i = 0; i < len; i++) { + keyword = kwlist[i]; if (*format == '|') { - if (min != INT_MAX) { - PyErr_SetString(PyExc_SystemError, - "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", - max, - max == 1 ? "" : "s", - nargs); - } - return cleanreturn(0, &freelist); - } } if (IS_END_OF_FORMAT(*format)) { - PyErr_Format(PyExc_SystemError, + PyErr_Format(PyExc_RuntimeError, "More keyword list entries (%d) than " "format specifiers (%d)", len, i); - return cleanreturn(0, &freelist); + 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; - } - 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); - } + current_arg = NULL; + if (nkeywords) { + current_arg = PyDict_GetItemString(keywords, keyword); } - - /* 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", - 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++) { - current_arg = _PyDict_GetItemStringWithError(kwargs, kwlist[i]); - if (current_arg) { + if (current_arg) { + --nkeywords; + if (i < nargs) { /* arg present in tuple and in dict */ PyErr_Format(PyExc_TypeError, - "argument for %.200s%s given by name ('%s') " + "Argument 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; - if (format) { - /* grab the function name or custom error msg first (mutually exclusive) */ - parser->fname = strchr(parser->format, ':'); - if (parser->fname) { - parser->fname++; - parser->custom_msg = NULL; - } - else { - parser->custom_msg = strchr(parser->format,';'); - if (parser->custom_msg) - parser->custom_msg++; - } - - min = max = INT_MAX; - for (i = 0; i < len; i++) { - if (*format == '|') { - if (min != INT_MAX) { - PyErr_SetString(PyExc_SystemError, - "Invalid format string (| specified twice)"); - return 0; - } - if (max != INT_MAX) { - PyErr_SetString(PyExc_SystemError, - "Invalid format string ($ before |)"); - return 0; - } - min = i; - format++; - } - if (*format == '$') { - if (max != INT_MAX) { - PyErr_SetString(PyExc_SystemError, - "Invalid format string ($ specified twice)"); - return 0; - } - if (i < parser->pos) { - PyErr_SetString(PyExc_SystemError, - "Empty parameter name after $"); - return 0; - } - 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; - } - - msg = skipitem(&format, NULL, 0); - if (msg) { - PyErr_Format(PyExc_SystemError, "%s: '%s'", msg, - format); - 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, - "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* -find_keyword(PyObject *kwnames, PyObject *const *kwstack, PyObject *key) -{ - Py_ssize_t i, nkwargs; - - nkwargs = PyTuple_GET_SIZE(kwnames); - for (i=0; i < nkwargs; i++) { - PyObject *kwname = PyTuple_GET_ITEM(kwnames, i); - - /* ptr==ptr should match in most cases since keyword keys - should be interned strings */ - if (kwname == key) { - return kwstack[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, - "%.200s%s takes %s %d positional argument%s (%zd given)", - (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); - if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { - return cleanreturn(0, &freelist); - } - } - else { - current_arg = find_keyword(kwnames, kwstack, keyword); - } - if (current_arg) { - --nkwargs; + keyword, i+1); + return cleanreturn(0, freelist); } } - else { - current_arg = NULL; - } + else if (nkeywords && PyErr_Occurred()) + return cleanreturn(0, freelist); + else if (i < nargs) + current_arg = PyTuple_GET_ITEM(args, i); 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); + seterror(i+1, msg, levels, fname, 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", - 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); + if (i < min) { + PyErr_Format(PyExc_TypeError, "Required argument " + "'%s' (pos %d) not found", + 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); - } + if (!nkeywords) + return cleanreturn(1, freelist); - /* We are into optional args, skip through to any remaining + /* We are into optional args, skip thru 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()) { - return cleanreturn(0, &freelist); - } - } - 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, - "'%S' is an invalid keyword " - "argument for %.200s%s", - keyword, - (parser->fname == NULL) ? "this function" : parser->fname, - (parser->fname == NULL) ? "" : "()"); - } - return cleanreturn(0, &freelist); - } + if (msg) { + PyErr_Format(PyExc_RuntimeError, "%s: '%s'", msg, + format); + 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); -} - - -#undef _PyArg_UnpackKeywords - -PyObject * const * -_PyArg_UnpackKeywords(PyObject *const *args, Py_ssize_t nargs, - PyObject *kwargs, PyObject *kwnames, - struct _PyArg_Parser *parser, - int minpos, int maxpos, int minkw, - PyObject **buf) -{ - PyObject *kwtuple; - PyObject *keyword; - int i, posonly, minposonly, maxargs; - int reqlimit = minkw ? maxpos + minkw : minpos; - Py_ssize_t nkwargs; - PyObject *current_arg; - PyObject * const *kwstack = NULL; - - assert(kwargs == NULL || PyDict_Check(kwargs)); - assert(kwargs == NULL || kwnames == NULL); - - if (parser == NULL) { - PyErr_BadInternalCall(); - return NULL; - } - - if (kwnames != NULL && !PyTuple_Check(kwnames)) { - PyErr_BadInternalCall(); - return NULL; - } - - if (args == NULL && nargs == 0) { - args = buf; - } - - if (!parser_init(parser)) { - return NULL; + if (!IS_END_OF_FORMAT(*format) && *format != '|') { + PyErr_Format(PyExc_RuntimeError, + "more argument specifiers than keyword list entries " + "(remaining format:'%s')", format); + return cleanreturn(0, freelist); } - kwtuple = parser->kwtuple; - posonly = parser->pos; - minposonly = Py_MIN(posonly, minpos); - maxargs = posonly + (int)PyTuple_GET_SIZE(kwtuple); - - if (kwargs != NULL) { - nkwargs = PyDict_GET_SIZE(kwargs); - } - else if (kwnames != NULL) { - nkwargs = PyTuple_GET_SIZE(kwnames); - kwstack = args + nargs; - } - else { - nkwargs = 0; - } - if (nkwargs == 0 && minkw == 0 && minpos <= nargs && nargs <= maxpos) { - /* Fast path. */ - return args; - } - if (nargs + nkwargs > maxargs) { - /* 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) ? "" : "()", - maxargs, - (nargs == 0) ? "keyword " : "", - (maxargs == 1) ? "" : "s", - nargs + nkwargs); - return NULL; - } - if (nargs > maxpos) { - if (maxpos == 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) ? "" : "()", - (minpos < maxpos) ? "at most" : "exactly", - maxpos, - (maxpos == 1) ? "" : "s", - nargs); - } - return NULL; - } - if (nargs < minposonly) { - PyErr_Format(PyExc_TypeError, - "%.200s%s takes %s %d positional argument%s" - " (%zd given)", - (parser->fname == NULL) ? "function" : parser->fname, - (parser->fname == NULL) ? "" : "()", - minposonly < maxpos ? "at least" : "exactly", - minposonly, - minposonly == 1 ? "" : "s", - nargs); - return NULL; - } - - /* copy tuple args */ - for (i = 0; i < nargs; i++) { - buf[i] = args[i]; - } - - /* copy keyword args using kwtuple to drive process */ - for (i = Py_MAX((int)nargs, posonly); i < maxargs; i++) { - if (nkwargs) { - keyword = PyTuple_GET_ITEM(kwtuple, i - posonly); - if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { - return NULL; - } - } - else { - current_arg = find_keyword(kwnames, kwstack, keyword); + /* make sure there are no extraneous keyword arguments */ + if (nkeywords > 0) { + PyObject *key, *value; + Py_ssize_t pos = 0; + while (PyDict_Next(keywords, &pos, &key, &value)) { + int match = 0; + char *ks; + if (!PyString_Check(key)) { + PyErr_SetString(PyExc_TypeError, + "keywords must be strings"); + return cleanreturn(0, freelist); } - } - else if (i >= reqlimit) { - break; - } - else { - current_arg = NULL; - } - - buf[i] = current_arg; - - if (current_arg) { - --nkwargs; - } - else if (i < minpos || (maxpos <= i && i < reqlimit)) { - /* Less arguments than required */ - keyword = PyTuple_GET_ITEM(kwtuple, i - posonly); - 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 NULL; - } - } - - if (nkwargs > 0) { - Py_ssize_t j; - /* make sure there are no arguments given by name and position */ - for (i = posonly; i < nargs; i++) { - keyword = PyTuple_GET_ITEM(kwtuple, i - posonly); - if (kwargs != NULL) { - current_arg = PyDict_GetItemWithError(kwargs, keyword); - if (!current_arg && PyErr_Occurred()) { - return NULL; + ks = PyString_AsString(key); + for (i = 0; i < len; i++) { + if (!strcmp(ks, kwlist[i])) { + match = 1; + break; } } - else { - current_arg = find_keyword(kwnames, kwstack, keyword); - } - if (current_arg) { - /* arg present in tuple and in dict */ + if (!match) { 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 NULL; - } - } - /* 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 NULL; + "'%s' is an invalid keyword " + "argument for this function", + ks); + return cleanreturn(0, freelist); } } } - return buf; + return cleanreturn(1, freelist); } -static const char * +static char * skipitem(const char **p_format, va_list *p_va, int flags) { const char *format = *p_format; @@ -2541,10 +1733,8 @@ skipitem(const char **p_format, va_list *p_va, int flags) switch (c) { - /* - * codes that take a single data pointer as an argument - * (the type of the pointer is irrelevant) - */ + /* simple codes + * The individual types (second arg of va_arg) are irrelevant */ case 'b': /* byte -- very short int */ case 'B': /* byte as bitfield */ @@ -2554,22 +1744,24 @@ skipitem(const char **p_format, va_list *p_va, int flags) 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 */ +#ifdef HAVE_LONG_LONG + case 'L': /* PY_LONG_LONG */ + case 'K': /* PY_LONG_LONG sized bitfield */ +#endif case 'f': /* float */ case 'd': /* double */ +#ifndef WITHOUT_COMPLEX case 'D': /* complex double */ +#endif 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 *); - } + (void) va_arg(*p_va, void *); + break; + } + + case 'n': /* Py_ssize_t */ + { + (void) va_arg(*p_va, Py_ssize_t *); break; } @@ -2577,75 +1769,68 @@ skipitem(const char **p_format, va_list *p_va, int flags) case 'e': /* string with encoding */ { - if (p_va != NULL) { - (void) va_arg(*p_va, const char *); - } + (void) va_arg(*p_va, const char *); if (!(*format == 's' || *format == 't')) /* after 'e', only 's' and 't' is allowed */ goto err; format++; + /* explicit fallthrough to string cases */ } - /* fall through */ case 's': /* string */ case 'z': /* string or None */ - case 'y': /* bytes */ +#ifdef Py_USING_UNICODE case 'u': /* unicode string */ - case 'Z': /* unicode string or None */ +#endif + case 't': /* buffer, read-only */ case 'w': /* buffer, read-write */ { - if (p_va != NULL) { - (void) va_arg(*p_va, char **); - } + (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 *); - } - } + if (flags & FLAG_SIZE_T) + (void) va_arg(*p_va, Py_ssize_t *); + else + (void) va_arg(*p_va, int *); format++; - } else if ((c == 's' || c == 'z' || c == 'y' || c == 'w') - && *format == '*') - { + } else if ((c == 's' || c == 'z' || c == 'w') && *format == '*') { format++; } break; } + /* object codes */ + + case 'S': /* string object */ +#ifdef Py_USING_UNICODE + case 'U': /* unicode string object */ +#endif + { + (void) va_arg(*p_va, PyObject **); + break; + } + case 'O': /* object */ { if (*format == '!') { format++; - if (p_va != NULL) { - (void) va_arg(*p_va, PyTypeObject*); - (void) va_arg(*p_va, PyObject **); - } + (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 *); - } + (void) va_arg(*p_va, converter); + (void) va_arg(*p_va, void *); format++; } else { - if (p_va != NULL) { - (void) va_arg(*p_va, PyObject **); - } + (void) va_arg(*p_va, PyObject **); } break; } case '(': /* bypass tuple, not handled at all previously */ { - const char *msg; + char *msg; for (;;) { if (*format==')') break; @@ -2674,172 +1859,88 @@ err: } -#undef _PyArg_CheckPositional - int -_PyArg_CheckPositional(const char *name, Py_ssize_t nargs, - Py_ssize_t min, Py_ssize_t max) +PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...) { + Py_ssize_t i, l; + PyObject **o; + va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, max); +#else + va_start(vargs); +#endif + assert(min >= 0); assert(min <= max); - - if (nargs < min) { + if (!PyTuple_Check(args)) { + va_end(vargs); + 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( PyExc_TypeError, - "%.200s expected %s%zd argument%s, got %zd", - name, (min == max ? "" : "at least "), min, min == 1 ? "" : "s", nargs); + "%s expected %s%zd arguments, got %zd", + name, (min == max ? "" : "at least "), min, l); else PyErr_Format( PyExc_TypeError, - "unpacked tuple should have %s%zd element%s," + "unpacked tuple should have %s%zd elements," " but has %zd", - (min == max ? "" : "at least "), min, min == 1 ? "" : "s", nargs); + (min == max ? "" : "at least "), min, l); + va_end(vargs); return 0; } - - if (nargs == 0) { - return 1; - } - - if (nargs > max) { + if (l > 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); + "%s expected %s%zd arguments, got %zd", + name, (min == max ? "" : "at most "), max, l); else PyErr_Format( PyExc_TypeError, - "unpacked tuple should have %s%zd element%s," + "unpacked tuple should have %s%zd elements," " but has %zd", - (min == max ? "" : "at most "), max, max == 1 ? "" : "s", nargs); + (min == max ? "" : "at most "), max, l); + va_end(vargs); return 0; } - - return 1; -} - -static int -unpack_stack(PyObject *const *args, Py_ssize_t nargs, const char *name, - Py_ssize_t min, Py_ssize_t max, va_list vargs) -{ - Py_ssize_t i; - PyObject **o; - - if (!_PyArg_CheckPositional(name, nargs, min, max)) { - return 0; - } - - for (i = 0; i < nargs; i++) { + 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; + *o = PyTuple_GET_ITEM(args, i); } - 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; + return 1; } -#undef _PyArg_NoKeywords -#undef _PyArg_NoPositional - /* For type constructors that don't take keyword args * - * Sets a TypeError and returns 0 if the args/kwargs is + * Sets a TypeError and returns 0 if the kwds dict is * not empty, returns 1 otherwise */ int -_PyArg_NoKeywords(const char *funcname, PyObject *kwargs) +_PyArg_NoKeywords(const char *funcname, PyObject *kw) { - if (kwargs == NULL) { + if (kw == NULL) return 1; - } - if (!PyDict_CheckExact(kwargs)) { + if (!PyDict_CheckExact(kw)) { PyErr_BadInternalCall(); return 0; } - if (PyDict_GET_SIZE(kwargs) == 0) { + if (PyDict_Size(kw) == 0) return 1; - } - PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", + PyErr_Format(PyExc_TypeError, "%s does not take 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; -} - -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 |