123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696 |
- /* Module support implementation */
- #include "Python.h"
- #include "pycore_abstract.h" // _PyIndex_Check()
- #include "pycore_object.h" // _PyType_IsReady()
- #define FLAG_SIZE_T 1
- 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*);
- int
- _Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
- {
- Py_ssize_t limit;
- if (obj == Py_None) {
- return 1;
- }
- else if (_PyIndex_Check(obj)) {
- limit = PyNumber_AsSsize_t(obj, PyExc_OverflowError);
- if (limit == -1 && PyErr_Occurred()) {
- return 0;
- }
- }
- else {
- PyErr_Format(PyExc_TypeError,
- "argument should be integer or None, not '%.200s'",
- Py_TYPE(obj)->tp_name);
- return 0;
- }
- *((Py_ssize_t *)result) = limit;
- return 1;
- }
- /* Helper for mkvalue() to scan the length of a format */
- static Py_ssize_t
- countformat(const char *format, char endchar)
- {
- Py_ssize_t count = 0;
- int level = 0;
- while (level > 0 || *format != endchar) {
- switch (*format) {
- case '\0':
- /* Premature end */
- PyErr_SetString(PyExc_SystemError,
- "unmatched paren in format");
- return -1;
- case '(':
- case '[':
- case '{':
- if (level == 0) {
- count++;
- }
- level++;
- break;
- case ')':
- case ']':
- case '}':
- level--;
- break;
- case '#':
- case '&':
- case ',':
- case ':':
- case ' ':
- case '\t':
- break;
- default:
- if (level == 0) {
- count++;
- }
- }
- format++;
- }
- return count;
- }
- /* 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 *, 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, char endchar, Py_ssize_t n, int flags)
- {
- assert(PyErr_Occurred());
- PyObject *v = PyTuple_New(n);
- for (Py_ssize_t i = 0; i < n; i++) {
- PyObject *exc = PyErr_GetRaisedException();
- PyObject *w = do_mkvalue(p_format, p_va, flags);
- PyErr_SetRaisedException(exc);
- if (w != NULL) {
- if (v != NULL) {
- PyTuple_SET_ITEM(v, i, w);
- }
- else {
- Py_DECREF(w);
- }
- }
- }
- Py_XDECREF(v);
- if (**p_format != endchar) {
- PyErr_SetString(PyExc_SystemError,
- "Unmatched paren in format");
- return;
- }
- if (endchar) {
- ++*p_format;
- }
- }
- static PyObject *
- do_mkdict(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
- {
- PyObject *d;
- Py_ssize_t i;
- if (n < 0)
- return NULL;
- if (n % 2) {
- PyErr_SetString(PyExc_SystemError,
- "Bad dict format");
- do_ignore(p_format, p_va, endchar, n, flags);
- return NULL;
- }
- /* Note that we can't bail immediately on error as this will leak
- refcounts on any 'N' arguments. */
- if ((d = PyDict_New()) == NULL) {
- do_ignore(p_format, p_va, endchar, n, flags);
- return NULL;
- }
- for (i = 0; i < n; i+= 2) {
- PyObject *k, *v;
- k = do_mkvalue(p_format, p_va, flags);
- if (k == NULL) {
- do_ignore(p_format, p_va, endchar, n - i - 1, flags);
- Py_DECREF(d);
- return NULL;
- }
- v = do_mkvalue(p_format, p_va, flags);
- if (v == NULL || PyDict_SetItem(d, k, v) < 0) {
- do_ignore(p_format, p_va, endchar, n - i - 2, flags);
- Py_DECREF(k);
- Py_XDECREF(v);
- Py_DECREF(d);
- return NULL;
- }
- Py_DECREF(k);
- Py_DECREF(v);
- }
- if (**p_format != endchar) {
- Py_DECREF(d);
- PyErr_SetString(PyExc_SystemError,
- "Unmatched paren in format");
- return NULL;
- }
- if (endchar)
- ++*p_format;
- return d;
- }
- static PyObject *
- do_mklist(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
- {
- PyObject *v;
- Py_ssize_t i;
- if (n < 0)
- return NULL;
- /* Note that we can't bail immediately on error as this will leak
- refcounts on any 'N' arguments. */
- v = PyList_New(n);
- if (v == NULL) {
- do_ignore(p_format, p_va, endchar, n, flags);
- return NULL;
- }
- 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);
- Py_DECREF(v);
- return NULL;
- }
- PyList_SET_ITEM(v, i, w);
- }
- if (**p_format != endchar) {
- Py_DECREF(v);
- PyErr_SetString(PyExc_SystemError,
- "Unmatched paren in format");
- return NULL;
- }
- if (endchar)
- ++*p_format;
- 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)
- {
- PyObject *v;
- Py_ssize_t i;
- if (n < 0)
- return NULL;
- /* Note that we can't bail immediately on error as this will leak
- refcounts on any 'N' arguments. */
- if ((v = PyTuple_New(n)) == NULL) {
- do_ignore(p_format, p_va, endchar, n, flags);
- return NULL;
- }
- 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);
- Py_DECREF(v);
- return NULL;
- }
- PyTuple_SET_ITEM(v, i, w);
- }
- if (**p_format != endchar) {
- Py_DECREF(v);
- PyErr_SetString(PyExc_SystemError,
- "Unmatched paren in format");
- return NULL;
- }
- if (endchar)
- ++*p_format;
- return v;
- }
- static PyObject *
- do_mkvalue(const char **p_format, va_list *p_va, int flags)
- {
- #define ERROR_NEED_PY_SSIZE_T_CLEAN \
- { \
- PyErr_SetString(PyExc_SystemError, \
- "PY_SSIZE_T_CLEAN macro must be defined for '#' formats"); \
- return NULL; \
- }
- for (;;) {
- switch (*(*p_format)++) {
- case '(':
- return do_mktuple(p_format, p_va, ')',
- countformat(*p_format, ')'), flags);
- case '[':
- return do_mklist(p_format, p_va, ']',
- countformat(*p_format, ']'), flags);
- case '{':
- return do_mkdict(p_format, p_va, '}',
- countformat(*p_format, '}'), flags);
- case 'b':
- case 'B':
- case 'h':
- case 'i':
- return PyLong_FromLong((long)va_arg(*p_va, int));
- case 'H':
- return PyLong_FromLong((long)va_arg(*p_va, unsigned int));
- case 'I':
- {
- unsigned int n;
- n = va_arg(*p_va, unsigned int);
- return PyLong_FromUnsignedLong(n);
- }
- case 'n':
- #if SIZEOF_SIZE_T!=SIZEOF_LONG
- return PyLong_FromSsize_t(va_arg(*p_va, Py_ssize_t));
- #endif
- /* Fall through from 'n' to 'l' if Py_ssize_t is long */
- case 'l':
- return PyLong_FromLong(va_arg(*p_va, long));
- case 'k':
- {
- unsigned long n;
- n = va_arg(*p_va, unsigned long);
- return PyLong_FromUnsignedLong(n);
- }
- case 'L':
- return PyLong_FromLongLong((long long)va_arg(*p_va, long long));
- case 'K':
- return PyLong_FromUnsignedLongLong((long long)va_arg(*p_va, unsigned long long));
- case 'u':
- {
- PyObject *v;
- Py_UNICODE *u = va_arg(*p_va, Py_UNICODE *);
- Py_ssize_t n;
- if (**p_format == '#') {
- ++*p_format;
- if (flags & FLAG_SIZE_T) {
- n = va_arg(*p_va, Py_ssize_t);
- }
- else {
- n = va_arg(*p_va, int);
- ERROR_NEED_PY_SSIZE_T_CLEAN;
- }
- }
- else
- n = -1;
- if (u == NULL) {
- v = Py_NewRef(Py_None);
- }
- else {
- if (n < 0)
- n = wcslen(u);
- v = PyUnicode_FromWideChar(u, n);
- }
- return v;
- }
- case 'f':
- case 'd':
- return PyFloat_FromDouble(
- (double)va_arg(*p_va, va_double));
- case 'D':
- return PyComplex_FromCComplex(
- *((Py_complex *)va_arg(*p_va, Py_complex *)));
- case 'c':
- {
- char p[1];
- p[0] = (char)va_arg(*p_va, int);
- return PyBytes_FromStringAndSize(p, 1);
- }
- case 'C':
- {
- int i = va_arg(*p_va, int);
- return PyUnicode_FromOrdinal(i);
- }
- case 's':
- case 'z':
- case 'U': /* XXX deprecated alias */
- {
- PyObject *v;
- const char *str = va_arg(*p_va, const char *);
- Py_ssize_t n;
- if (**p_format == '#') {
- ++*p_format;
- if (flags & FLAG_SIZE_T) {
- n = va_arg(*p_va, Py_ssize_t);
- }
- else {
- n = va_arg(*p_va, int);
- ERROR_NEED_PY_SSIZE_T_CLEAN;
- }
- }
- else
- n = -1;
- if (str == NULL) {
- v = Py_NewRef(Py_None);
- }
- else {
- if (n < 0) {
- size_t m = strlen(str);
- if (m > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "string too long for Python string");
- return NULL;
- }
- n = (Py_ssize_t)m;
- }
- v = PyUnicode_FromStringAndSize(str, n);
- }
- return v;
- }
- case 'y':
- {
- PyObject *v;
- const char *str = va_arg(*p_va, const char *);
- Py_ssize_t n;
- if (**p_format == '#') {
- ++*p_format;
- if (flags & FLAG_SIZE_T) {
- n = va_arg(*p_va, Py_ssize_t);
- }
- else {
- n = va_arg(*p_va, int);
- ERROR_NEED_PY_SSIZE_T_CLEAN;
- }
- }
- else
- n = -1;
- if (str == NULL) {
- v = Py_NewRef(Py_None);
- }
- else {
- if (n < 0) {
- size_t m = strlen(str);
- if (m > PY_SSIZE_T_MAX) {
- PyErr_SetString(PyExc_OverflowError,
- "string too long for Python bytes");
- return NULL;
- }
- n = (Py_ssize_t)m;
- }
- v = PyBytes_FromStringAndSize(str, n);
- }
- return v;
- }
- case 'N':
- case 'S':
- case 'O':
- if (**p_format == '&') {
- typedef PyObject *(*converter)(void *);
- converter func = va_arg(*p_va, converter);
- void *arg = va_arg(*p_va, void *);
- ++*p_format;
- return (*func)(arg);
- }
- else {
- PyObject *v;
- v = va_arg(*p_va, PyObject *);
- if (v != NULL) {
- if (*(*p_format - 1) != 'N')
- Py_INCREF(v);
- }
- else if (!PyErr_Occurred())
- /* If a NULL was passed
- * because a call that should
- * have constructed a value
- * failed, that's OK, and we
- * pass the error on; but if
- * no error occurred it's not
- * clear that the caller knew
- * what she was doing. */
- PyErr_SetString(PyExc_SystemError,
- "NULL object passed to Py_BuildValue");
- return v;
- }
- case ':':
- case ',':
- case ' ':
- case '\t':
- break;
- default:
- PyErr_SetString(PyExc_SystemError,
- "bad format char passed to Py_BuildValue");
- return NULL;
- }
- }
- #undef ERROR_NEED_PY_SSIZE_T_CLEAN
- }
- PyObject *
- Py_BuildValue(const char *format, ...)
- {
- va_list va;
- PyObject* retval;
- va_start(va, format);
- retval = va_build_value(format, va, 0);
- va_end(va);
- return retval;
- }
- PyObject *
- _Py_BuildValue_SizeT(const char *format, ...)
- {
- va_list va;
- PyObject* retval;
- va_start(va, format);
- retval = va_build_value(format, va, FLAG_SIZE_T);
- va_end(va);
- return retval;
- }
- PyObject *
- Py_VaBuildValue(const char *format, va_list va)
- {
- return va_build_value(format, va, 0);
- }
- PyObject *
- _Py_VaBuildValue_SizeT(const char *format, va_list va)
- {
- return va_build_value(format, va, FLAG_SIZE_T);
- }
- static PyObject *
- va_build_value(const char *format, va_list va, int flags)
- {
- const char *f = format;
- Py_ssize_t n = countformat(f, '\0');
- va_list lva;
- PyObject *retval;
- if (n < 0)
- return NULL;
- if (n == 0) {
- Py_RETURN_NONE;
- }
- va_copy(lva, va);
- if (n == 1) {
- retval = do_mkvalue(&f, &lva, flags);
- } else {
- retval = do_mktuple(&f, &lva, '\0', n, flags);
- }
- va_end(lva);
- 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) {
- if (stack != small_stack) {
- PyMem_Free(stack);
- }
- return NULL;
- }
- *p_nargs = n;
- return stack;
- }
- int
- PyModule_AddObjectRef(PyObject *mod, const char *name, PyObject *value)
- {
- if (!PyModule_Check(mod)) {
- PyErr_SetString(PyExc_TypeError,
- "PyModule_AddObjectRef() first argument "
- "must be a module");
- return -1;
- }
- if (!value) {
- if (!PyErr_Occurred()) {
- PyErr_SetString(PyExc_SystemError,
- "PyModule_AddObjectRef() must be called "
- "with an exception raised if value is NULL");
- }
- return -1;
- }
- PyObject *dict = PyModule_GetDict(mod);
- if (dict == NULL) {
- /* Internal error -- modules must have a dict! */
- PyErr_Format(PyExc_SystemError, "module '%s' has no __dict__",
- PyModule_GetName(mod));
- return -1;
- }
- return PyDict_SetItemString(dict, name, value);
- }
- int
- _PyModule_Add(PyObject *mod, const char *name, PyObject *value)
- {
- int res = PyModule_AddObjectRef(mod, name, value);
- Py_XDECREF(value);
- return res;
- }
- int
- PyModule_AddObject(PyObject *mod, const char *name, PyObject *value)
- {
- int res = PyModule_AddObjectRef(mod, name, value);
- if (res == 0) {
- Py_DECREF(value);
- }
- return res;
- }
- int
- PyModule_AddIntConstant(PyObject *m, const char *name, long value)
- {
- return _PyModule_Add(m, name, PyLong_FromLong(value));
- }
- int
- PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
- {
- return _PyModule_Add(m, name, PyUnicode_FromString(value));
- }
- int
- PyModule_AddType(PyObject *module, PyTypeObject *type)
- {
- if (!_PyType_IsReady(type) && PyType_Ready(type) < 0) {
- return -1;
- }
- const char *name = _PyType_Name(type);
- assert(name != NULL);
- return PyModule_AddObjectRef(module, name, (PyObject *)type);
- }
|