summaryrefslogtreecommitdiffstats
path: root/Python/getargs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/getargs.c')
-rw-r--r--Python/getargs.c2447
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