diff options
Diffstat (limited to 'Python/modsupport.c')
| -rw-r--r-- | Python/modsupport.c | 151 | 
1 files changed, 126 insertions, 25 deletions
| diff --git a/Python/modsupport.c b/Python/modsupport.c index aabee8f..01b5dc9 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,7 +507,7 @@ 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; @@ -485,9 +527,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 +602,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 +610,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; | 
