From a046370f668b75a91f70292614ab7f5492cfed9a Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Sun, 17 Feb 2013 01:04:57 +0100 Subject: Issue #17170: speed up PyArg_ParseTuple[AndKeywords] a bit. --- Python/getargs.c | 57 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index ae931b92aa..08faeb464d 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -46,10 +46,12 @@ typedef struct { } freelistentry_t; typedef struct { - int first_available; freelistentry_t *entries; + int first_available; + int entries_malloced; } freelist_t; +#define STATIC_FREELIST_ENTRIES 8 /* Forward */ static int vgetargs1(PyObject *, const char *, va_list *, int); @@ -187,7 +189,8 @@ cleanreturn(int retval, freelist_t *freelist) freelist->entries[index].item); } } - PyMem_FREE(freelist->entries); + if (freelist->entries_malloced) + PyMem_FREE(freelist->entries); return retval; } @@ -197,6 +200,8 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) { char msgbuf[256]; int levels[32]; + freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; + freelist_t freelist = {static_entries, 0, 0}; const char *fname = NULL; const char *message = NULL; int min = -1; @@ -206,7 +211,6 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) const char *formatsave = format; Py_ssize_t i, len; char *msg; - freelist_t freelist = {0, NULL}; int compat = flags & FLAG_COMPAT; assert(compat || (args != (PyObject*)NULL)); @@ -240,15 +244,15 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) message = format; endfmt = 1; break; + case '|': + if (level == 0) + min = max; + break; default: if (level == 0) { - if (c == 'O') - max++; - else if (Py_ISALPHA(Py_CHARMASK(c))) { + if (Py_ISALPHA(Py_CHARMASK(c))) if (c != 'e') /* skip encoded */ max++; - } else if (c == '|') - min = max; } break; } @@ -262,10 +266,13 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) format = formatsave; - freelist.entries = PyMem_NEW(freelistentry_t, max); - if (freelist.entries == NULL) { - PyErr_NoMemory(); - return 0; + 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) { @@ -1421,7 +1428,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, int max = INT_MAX; int i, len, nargs, nkeywords; PyObject *current_arg; - freelist_t freelist = {0, NULL}; + freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; + freelist_t freelist = {static_entries, 0, 0}; assert(args != NULL && PyTuple_Check(args)); assert(keywords == NULL || PyDict_Check(keywords)); @@ -1445,10 +1453,13 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, for (len=0; kwlist[len]; len++) continue; - freelist.entries = PyMem_NEW(freelistentry_t, len); - if (freelist.entries == NULL) { - PyErr_NoMemory(); - return 0; + if (len > STATIC_FREELIST_ENTRIES) { + freelist.entries = PyMem_NEW(freelistentry_t, len); + if (freelist.entries == NULL) { + PyErr_NoMemory(); + return 0; + } + freelist.entries_malloced = 1; } nargs = PyTuple_GET_SIZE(args); @@ -1574,20 +1585,16 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, Py_ssize_t pos = 0; while (PyDict_Next(keywords, &pos, &key, &value)) { int match = 0; - char *ks; if (!PyUnicode_Check(key)) { PyErr_SetString(PyExc_TypeError, "keywords must be strings"); return cleanreturn(0, &freelist); } /* check that _PyUnicode_AsString() result is not NULL */ - ks = _PyUnicode_AsString(key); - if (ks != NULL) { - for (i = 0; i < len; i++) { - if (!strcmp(ks, kwlist[i])) { - match = 1; - break; - } + for (i = 0; i < len; i++) { + if (!PyUnicode_CompareWithASCIIString(key, kwlist[i])) { + match = 1; + break; } } if (!match) { -- cgit v1.2.1 From 56ab3a7c859cf948aa42a5a04ae15dcadb89bbf9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 17 May 2013 00:12:04 +0200 Subject: Fix compilater warnings on Windows 64-bit --- Python/getargs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 08faeb464d..87b6a6e3b2 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -55,7 +55,7 @@ typedef struct { /* Forward */ static int vgetargs1(PyObject *, const char *, va_list *, int); -static void seterror(int, const char *, int *, const char *, const char *); +static void seterror(Py_ssize_t, const char *, int *, const char *, const char *); static char *convertitem(PyObject *, const char **, va_list *, int, int *, char *, size_t, freelist_t *); static char *converttuple(PyObject *, const char **, va_list *, int, @@ -357,7 +357,7 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) static void -seterror(int iarg, const char *msg, int *levels, const char *fname, +seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, const char *message) { char buf[512]; @@ -373,7 +373,7 @@ seterror(int iarg, const char *msg, int *levels, const char *fname, } if (iarg != 0) { PyOS_snprintf(p, sizeof(buf) - (p - buf), - "argument %d", iarg); + "argument %zd", iarg); i = 0; p += strlen(p); while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { -- cgit v1.2.1 From 2d5dd12d267fefe2b43ceb735ba0b55c53069199 Mon Sep 17 00:00:00 2001 From: Richard Oudkerk Date: Sat, 18 May 2013 17:35:19 +0100 Subject: Use PY_FORMAT_SIZE_T because Visual Studio does not understand %zd format. --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 87b6a6e3b2..bdf1a0c193 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -373,7 +373,7 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, } if (iarg != 0) { PyOS_snprintf(p, sizeof(buf) - (p - buf), - "argument %zd", iarg); + "argument %" PY_FORMAT_SIZE_T "d", iarg); i = 0; p += strlen(p); while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { -- cgit v1.2.1 From dc9c5be72b968dfeb5b258608376ae3ec5adefaf Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 5 Jun 2013 01:18:13 +0200 Subject: Issue #9566: Fix compilater warnings on Windows 64-bit --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index bdf1a0c193..2c2628f9a1 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -570,7 +570,7 @@ 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=s; \ + *q = (int)s; \ } #define BUFFER_LEN ((flags & FLAG_SIZE_T) ? *q2:*q) #define RETURN_ERR_OCCURRED return msgbuf -- cgit v1.2.1 From 974d2756fd201ab5ac4b5005fbe8f288e9eb441a Mon Sep 17 00:00:00 2001 From: Georg Brandl Date: Mon, 14 Oct 2013 07:01:11 +0200 Subject: Re #18521: move array bounds check before array access. --- Python/getargs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 2c2628f9a1..9d72752320 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -376,7 +376,7 @@ seterror(Py_ssize_t iarg, const char *msg, int *levels, const char *fname, "argument %" PY_FORMAT_SIZE_T "d", iarg); i = 0; p += strlen(p); - while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { + while (i < 32 && levels[i] > 0 && (int)(p-buf) < 220) { PyOS_snprintf(p, sizeof(buf) - (p - buf), ", item %d", levels[i]-1); p += strlen(p); -- cgit v1.2.1 From f1abd93e823ef3bd3e14c276e42f0d8e8f9082d9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 7 Nov 2013 00:53:56 +0100 Subject: remove an outdated comment The comment is meaningless since changeset 4e985a96a612. --- Python/getargs.c | 1 - 1 file changed, 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 9d72752320..f313a37938 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1590,7 +1590,6 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, "keywords must be strings"); return cleanreturn(0, &freelist); } - /* check that _PyUnicode_AsString() result is not NULL */ for (i = 0; i < len; i++) { if (!PyUnicode_CompareWithASCIIString(key, kwlist[i])) { match = 1; -- cgit v1.2.1 From 51001c0c590d689d83148dac7094476bd7a54a27 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 18 Nov 2013 01:21:12 +0100 Subject: Use Py_ssize_t type for sizes in getargs.c Fix compiler warnings on Windows 64-bit --- Python/getargs.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index f313a37938..2cc3031c17 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -421,6 +421,7 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int n = 0; const char *format = *p_format; int i; + Py_ssize_t len; for (;;) { int c = *format++; @@ -450,12 +451,20 @@ converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, return msgbuf; } - if ((i = PySequence_Size(arg)) != n) { + len = PySequence_Size(arg); + if (len != n) { levels[0] = 0; - PyOS_snprintf(msgbuf, bufsize, - toplevel ? "expected %d arguments, not %d" : - "must be sequence of length %d, not %d", - n, i); + if (toplevel) { + PyOS_snprintf(msgbuf, bufsize, + "expected %d arguments, not %" PY_FORMAT_SIZE_T "d", + n, len); + } + else { + PyOS_snprintf(msgbuf, bufsize, + "must be sequence of length %d, " + "not %" PY_FORMAT_SIZE_T "d", + n, len); + } return msgbuf; } @@ -1426,7 +1435,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, const char *fname, *msg, *custom_msg, *keyword; int min = INT_MAX; int max = INT_MAX; - int i, len, nargs, nkeywords; + int i, len; + Py_ssize_t nargs, nkeywords; PyObject *current_arg; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; freelist_t freelist = {static_entries, 0, 0}; @@ -1466,7 +1476,8 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, 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)", + "%s%s takes at most %d argument%s " + "(%" PY_FORMAT_SIZE_T "d given)", (fname == NULL) ? "function" : fname, (fname == NULL) ? "" : "()", len, -- cgit v1.2.1 From 1549e115f9c53c9f72945a487c6a5f8fae0ba749 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 18 Nov 2013 02:05:31 +0100 Subject: PY_FORMAT_SIZE_T should not be used with PyErr_Format(), PyErr_Format("%zd") is portable --- Python/getargs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 2cc3031c17..60845680fc 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1476,8 +1476,7 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, nkeywords = (keywords == NULL) ? 0 : PyDict_Size(keywords); if (nargs + nkeywords > len) { PyErr_Format(PyExc_TypeError, - "%s%s takes at most %d argument%s " - "(%" PY_FORMAT_SIZE_T "d given)", + "%s%s takes at most %d argument%s (%zd given)", (fname == NULL) ? "function" : fname, (fname == NULL) ? "" : "()", len, -- cgit v1.2.1 From 3b8cbf3d534b72fde24a2e5e324e3c01b6df448b Mon Sep 17 00:00:00 2001 From: Larry Hastings Date: Sat, 18 Jan 2014 23:50:21 -0800 Subject: Issue #20294: Argument Clinic now supports argument parsing for __new__ and __init__ functions. --- Python/getargs.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index 60845680fc..bfea1118fd 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1805,7 +1805,7 @@ PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t m /* For type constructors that don't take keyword args * - * Sets a TypeError and returns 0 if the kwds dict is + * Sets a TypeError and returns 0 if the args/kwargs is * not empty, returns 1 otherwise */ int @@ -1824,6 +1824,25 @@ _PyArg_NoKeywords(const char *funcname, PyObject *kw) 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, "%s does not take positional arguments", + funcname); + return 0; +} + #ifdef __cplusplus }; #endif -- cgit v1.2.1 From 1ee15b415c2c59c2b74b40540581724299174270 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 11 Feb 2014 10:09:27 -0500 Subject: remove dynamic initializer lists for c89 compliance (closes #20595) --- Python/getargs.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'Python/getargs.c') diff --git a/Python/getargs.c b/Python/getargs.c index bfea1118fd..946faf2d7e 100644 --- a/Python/getargs.c +++ b/Python/getargs.c @@ -200,8 +200,6 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) { char msgbuf[256]; int levels[32]; - freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; - freelist_t freelist = {static_entries, 0, 0}; const char *fname = NULL; const char *message = NULL; int min = -1; @@ -212,6 +210,12 @@ vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) Py_ssize_t i, len; char *msg; int compat = flags & FLAG_COMPAT; + freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; + freelist_t freelist; + + freelist.entries = static_entries; + freelist.first_available = 0; + freelist.entries_malloced = 0; assert(compat || (args != (PyObject*)NULL)); flags = flags & ~FLAG_COMPAT; @@ -1439,7 +1443,11 @@ vgetargskeywords(PyObject *args, PyObject *keywords, const char *format, Py_ssize_t nargs, nkeywords; PyObject *current_arg; freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; - freelist_t freelist = {static_entries, 0, 0}; + freelist_t freelist; + + freelist.entries = static_entries; + freelist.first_available = 0; + freelist.entries_malloced = 0; assert(args != NULL && PyTuple_Check(args)); assert(keywords == NULL || PyDict_Check(keywords)); -- cgit v1.2.1