summaryrefslogtreecommitdiff
path: root/Python/modsupport.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-12-09 00:29:49 +0100
committerVictor Stinner <victor.stinner@gmail.com>2016-12-09 00:29:49 +0100
commit11f151148109fc852ee46023f9009a3c26a2bfab (patch)
treecef7c873af141e24899ae0dc2d007a6442fe57e1 /Python/modsupport.c
parent8625dcf86a2f10dcc375c95ac9fd0778b842e4f7 (diff)
downloadcpython-11f151148109fc852ee46023f9009a3c26a2bfab.tar.gz
Add _Py_VaBuildStack() function
Issue #28915: Similar to Py_VaBuildValue(), but work on a C array of PyObject*, instead of creating a tuple.
Diffstat (limited to 'Python/modsupport.c')
-rw-r--r--Python/modsupport.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/Python/modsupport.c b/Python/modsupport.c
index eef79c460f..01b5dc9dda 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -7,6 +7,7 @@
typedef double va_double;
static PyObject *va_build_value(const char *, va_list, int);
+static PyObject **va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len, const char *, va_list, int, Py_ssize_t*);
/* Package context -- the full module name for package imports */
const char *_Py_PackageContext = NULL;
@@ -60,6 +61,7 @@ countformat(const char *format, char endchar)
/* After an original idea and first implementation by Steven Miale */
static PyObject *do_mktuple(const char**, va_list *, char, Py_ssize_t, int);
+static int do_mkstack(PyObject **, const char**, va_list *, char, Py_ssize_t, int);
static PyObject *do_mklist(const char**, va_list *, char, Py_ssize_t, int);
static PyObject *do_mkdict(const char**, va_list *, char, Py_ssize_t, int);
static PyObject *do_mkvalue(const char**, va_list *, int);
@@ -182,6 +184,43 @@ do_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int
return v;
}
+static int
+do_mkstack(PyObject **stack, const char **p_format, va_list *p_va,
+ char endchar, Py_ssize_t n, int flags)
+{
+ Py_ssize_t i;
+
+ if (n < 0) {
+ return -1;
+ }
+ /* Note that we can't bail immediately on error as this will leak
+ refcounts on any 'N' arguments. */
+ for (i = 0; i < n; i++) {
+ PyObject *w = do_mkvalue(p_format, p_va, flags);
+ if (w == NULL) {
+ do_ignore(p_format, p_va, endchar, n - i - 1, flags);
+ goto error;
+ }
+ stack[i] = w;
+ }
+ if (**p_format != endchar) {
+ PyErr_SetString(PyExc_SystemError,
+ "Unmatched paren in format");
+ goto error;
+ }
+ if (endchar) {
+ ++*p_format;
+ }
+ return 0;
+
+error:
+ n = i;
+ for (i=0; i < n; i++) {
+ Py_DECREF(stack[i]);
+ }
+ return -1;
+}
+
static PyObject *
do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
@@ -488,6 +527,65 @@ va_build_value(const char *format, va_list va, int flags)
return retval;
}
+PyObject **
+_Py_VaBuildStack(PyObject **small_stack, Py_ssize_t small_stack_len,
+ const char *format, va_list va, Py_ssize_t *p_nargs)
+{
+ return va_build_stack(small_stack, small_stack_len, format, va, 0, p_nargs);
+}
+
+PyObject **
+_Py_VaBuildStack_SizeT(PyObject **small_stack, Py_ssize_t small_stack_len,
+ const char *format, va_list va, Py_ssize_t *p_nargs)
+{
+ return va_build_stack(small_stack, small_stack_len, format, va, FLAG_SIZE_T, p_nargs);
+}
+
+static PyObject **
+va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len,
+ const char *format, va_list va, int flags, Py_ssize_t *p_nargs)
+{
+ const char *f;
+ Py_ssize_t n;
+ va_list lva;
+ PyObject **stack;
+ int res;
+
+ n = countformat(format, '\0');
+ if (n < 0) {
+ *p_nargs = 0;
+ return NULL;
+ }
+
+ if (n == 0) {
+ *p_nargs = 0;
+ return small_stack;
+ }
+
+ if (n <= small_stack_len) {
+ stack = small_stack;
+ }
+ else {
+ stack = PyMem_Malloc(n * sizeof(stack[0]));
+ if (stack == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ }
+
+ va_copy(lva, va);
+ f = format;
+ res = do_mkstack(stack, &f, &lva, '\0', n, flags);
+ va_end(lva);
+
+ if (res < 0) {
+ return NULL;
+ }
+
+ *p_nargs = n;
+ return stack;
+}
+
PyObject *
PyEval_CallFunction(PyObject *callable, const char *format, ...)