summaryrefslogtreecommitdiff
path: root/Python/modsupport.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/modsupport.c')
-rw-r--r--Python/modsupport.c154
1 files changed, 127 insertions, 27 deletions
diff --git a/Python/modsupport.c b/Python/modsupport.c
index aabee8fa59..e9e025bdb2 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -7,16 +7,17 @@
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 */
-char *_Py_PackageContext = NULL;
+const char *_Py_PackageContext = NULL;
/* Helper for mkvalue() to scan the length of a format */
-static int
-countformat(const char *format, int endchar)
+static Py_ssize_t
+countformat(const char *format, char endchar)
{
- int count = 0;
+ Py_ssize_t count = 0;
int level = 0;
while (level > 0 || *format != endchar) {
switch (*format) {
@@ -28,8 +29,9 @@ countformat(const char *format, int endchar)
case '(':
case '[':
case '{':
- if (level == 0)
+ if (level == 0) {
count++;
+ }
level++;
break;
case ')':
@@ -45,8 +47,9 @@ countformat(const char *format, int endchar)
case '\t':
break;
default:
- if (level == 0)
+ if (level == 0) {
count++;
+ }
}
format++;
}
@@ -57,17 +60,18 @@ countformat(const char *format, int endchar)
/* Generic function to create a value -- the inverse of getargs() */
/* After an original idea and first implementation by Steven Miale */
-static PyObject *do_mktuple(const char**, va_list *, int, int, int);
-static PyObject *do_mklist(const char**, va_list *, int, int, int);
-static PyObject *do_mkdict(const char**, va_list *, int, int, int);
+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);
static void
-do_ignore(const char **p_format, va_list *p_va, int endchar, int n, int flags)
+do_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *v;
- int i;
+ Py_ssize_t i;
assert(PyErr_Occurred());
v = PyTuple_New(n);
for (i = 0; i < n; i++) {
@@ -91,15 +95,16 @@ do_ignore(const char **p_format, va_list *p_va, int endchar, int n, int flags)
"Unmatched paren in format");
return;
}
- if (endchar)
+ if (endchar) {
++*p_format;
+ }
}
static PyObject *
-do_mkdict(const char **p_format, va_list *p_va, int endchar, int n, int flags)
+do_mkdict(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *d;
- int i;
+ Py_ssize_t i;
if (n < 0)
return NULL;
if (n % 2) {
@@ -146,10 +151,10 @@ do_mkdict(const char **p_format, va_list *p_va, int endchar, int n, int flags)
}
static PyObject *
-do_mklist(const char **p_format, va_list *p_va, int endchar, int n, int flags)
+do_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *v;
- int i;
+ Py_ssize_t i;
if (n < 0)
return NULL;
/* Note that we can't bail immediately on error as this will leak
@@ -179,11 +184,48 @@ do_mklist(const char **p_format, va_list *p_va, int endchar, int n, int flags)
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, int endchar, int n, int flags)
+do_mktuple(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
{
PyObject *v;
- int i;
+ Py_ssize_t i;
if (n < 0)
return NULL;
/* Note that we can't bail immediately on error as this will leak
@@ -286,8 +328,8 @@ do_mkvalue(const char **p_format, va_list *p_va, int flags)
}
else {
if (n < 0)
- n = Py_UNICODE_strlen(u);
- v = PyUnicode_FromUnicode(u, n);
+ n = wcslen(u);
+ v = PyUnicode_FromWideChar(u, n);
}
return v;
}
@@ -465,15 +507,14 @@ static PyObject *
va_build_value(const char *format, va_list va, int flags)
{
const char *f = format;
- int n = countformat(f, '\0');
+ Py_ssize_t n = countformat(f, '\0');
va_list lva;
PyObject *retval;
if (n < 0)
return NULL;
if (n == 0) {
- Py_INCREF(Py_None);
- return Py_None;
+ Py_RETURN_NONE;
}
va_copy(lva, va);
if (n == 1) {
@@ -485,9 +526,68 @@ 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 *obj, const char *format, ...)
+PyEval_CallFunction(PyObject *callable, const char *format, ...)
{
va_list vargs;
PyObject *args;
@@ -501,7 +601,7 @@ PyEval_CallFunction(PyObject *obj, const char *format, ...)
if (args == NULL)
return NULL;
- res = PyEval_CallObject(obj, args);
+ res = PyEval_CallObject(callable, args);
Py_DECREF(args);
return res;
@@ -509,14 +609,14 @@ PyEval_CallFunction(PyObject *obj, const char *format, ...)
PyObject *
-PyEval_CallMethod(PyObject *obj, const char *methodname, const char *format, ...)
+PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...)
{
va_list vargs;
PyObject *meth;
PyObject *args;
PyObject *res;
- meth = PyObject_GetAttrString(obj, methodname);
+ meth = PyObject_GetAttrString(obj, name);
if (meth == NULL)
return NULL;