Add _Py_VaBuildStack() function

Issue #28915: Similar to Py_VaBuildValue(), but work on a C array of PyObject*,
instead of creating a tuple.
diff --git a/Python/modsupport.c b/Python/modsupport.c
index eef79c4..01b5dc9 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 @@
 /* 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 @@
     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 @@
     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, ...)