/* New getargs implementation */ #include "Python.h" #include <ctype.h> #ifdef __cplusplusextern "C" { #endifint PyArg_Parse(PyObject *, const char *, ...);int PyArg_ParseTuple(PyObject *, const char *, ...);int PyArg_VaParse(PyObject *, const char *, va_list); int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, const char *, char **, ...);int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, const char *, char **, va_list); #ifdef HAVE_DECLSPEC_DLL/* Export functions */PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, char *, ...);PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, char *, ...);PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *, const char *, char **, ...);PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...);PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, char *, va_list);PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *, const char *, char **, va_list);#endif #define FLAG_COMPAT 1#define FLAG_SIZE_T 2 /* Forward */static int vgetargs1(PyObject *, const char *, va_list *, int);static void seterror(int, const char *, int *, const char *, const char *);static char *convertitem(PyObject *, const char **, va_list *, int, int *, char *, size_t, PyObject **);static char *converttuple(PyObject *, const char **, va_list *, int, int *, char *, size_t, int, PyObject **);static char *convertsimple(PyObject *, const char **, va_list *, int, char *, size_t, PyObject **);static Py_ssize_t convertbuffer(PyObject *, void **p, char **); static int vgetargskeywords(PyObject *, PyObject *, const char *, char **, va_list *, int);static char *skipitem(const char **, va_list *, int); intPyArg_Parse(PyObject *args, const char *format, ...){ int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, FLAG_COMPAT); va_end(va); return retval;} int_PyArg_Parse_SizeT(PyObject *args, char *format, ...){ int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); va_end(va); return retval;} intPyArg_ParseTuple(PyObject *args, const char *format, ...){ int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, 0); va_end(va); return retval;} int_PyArg_ParseTuple_SizeT(PyObject *args, char *format, ...){ int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, FLAG_SIZE_T); va_end(va); return retval;} intPyArg_VaParse(PyObject *args, const char *format, va_list va){ va_list lva; #ifdef VA_LIST_IS_ARRAY memcpy(lva, va, sizeof(va_list));#else#ifdef __va_copy __va_copy(lva, va);#else lva = va;#endif#endif return vgetargs1(args, format, &lva, 0);} int_PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va){ va_list lva; #ifdef VA_LIST_IS_ARRAY memcpy(lva, va, sizeof(va_list));#else#ifdef __va_copy __va_copy(lva, va);#else lva = va;#endif#endif return vgetargs1(args, format, &lva, FLAG_SIZE_T);} /* Handle cleanup of allocated memory in case of exception */ static intaddcleanup(void *ptr, PyObject **freelist){ PyObject *cobj; if (!*freelist) { *freelist = PyList_New(0); if (!*freelist) { PyMem_FREE(ptr); return -1; } } cobj = PyCObject_FromVoidPtr(ptr, NULL); if (!cobj) { PyMem_FREE(ptr); return -1; } if(PyList_Append(*freelist, cobj)) { PyMem_FREE(ptr); Py_DECREF(cobj); return -1; } Py_DECREF(cobj); return 0;} static intcleanreturn(int retval, PyObject *freelist){ if(freelist) { if((retval) == 0) { Py_ssize_t len = PyList_GET_SIZE(freelist), i; for (i = 0; i < len; i++) PyMem_FREE(PyCObject_AsVoidPtr( PyList_GET_ITEM(freelist, i))); } Py_DECREF(freelist); } return retval;} static intvgetargs1(PyObject *args, const char *format, va_list *p_va, int flags){ char msgbuf[256]; int levels[32]; const char *fname = NULL; const char *message = NULL; int min = -1; int max = 0; int level = 0; int endfmt = 0; const char *formatsave = format; Py_ssize_t i, len; char *msg; PyObject *freelist = NULL; int compat = flags & FLAG_COMPAT; assert(compat || (args != (PyObject*)NULL)); flags = flags & ~FLAG_COMPAT; while (endfmt == 0) { int c = *format++; switch (c) { case '(': if (level == 0) max++; level++; if (level >= 30) Py_FatalError("too many tuple nesting levels " "in argument format string"); break; case ')': if (level == 0) Py_FatalError("excess ')' in getargs format"); else level--; break; case '\0': endfmt = 1; break; case ':': fname = format; endfmt = 1; break; case ';': message = format; endfmt = 1; break; default: if (level == 0) { if (c == 'O') max++; else if (isalpha(Py_CHARMASK(c))) { if (c != 'e') /* skip encoded */ max++; } else if (c == '|') min = max; } break; } } if (level != 0) Py_FatalError(/* '(' */ "missing ')' in getargs format"); if (min < 0) min = max; format = formatsave; if (compat) { if (max == 0) { if (args == NULL) return 1; PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.200s%s takes no arguments", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); PyErr_SetString(PyExc_TypeError, msgbuf); return 0; } else if (min == 1 && max == 1) { if (args == NULL) { PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.200s%s takes at least one argument", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); PyErr_SetString(PyExc_TypeError, msgbuf); return 0; } msg = convertitem(args, &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg == NULL) return cleanreturn(1, freelist); seterror(levels[0], msg, levels+1, fname, message); return cleanreturn(0, freelist); } else { PyErr_SetString(PyExc_SystemError, "old style getargs format uses new features"); return 0; } } if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_SystemError, "new style getargs format but argument is not a tuple"); return 0; } len = PyTuple_GET_SIZE(args); if (len < min || max < len) { if (message == NULL) { PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.150s%s takes %s %d argument%s " "(%ld given)", fname==NULL ? "function" : fname, fname==NULL ? "" : "()", min==max ? "exactly" : len < min ? "at least" : "at most", len < min ? min : max, (len < min ? min : max) == 1 ? "" : "s", Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); message = msgbuf; } PyErr_SetString(PyExc_TypeError, message); return 0; } for (i = 0; i < len; i++) { if (*format == '|') format++; msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg) { seterror(i+1, msg, levels, fname, message); return cleanreturn(0, freelist); } } if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) && *format != '(' && *format != '|' && *format != ':' && *format != ';') { PyErr_Format(PyExc_SystemError, "bad format string: %.200s", formatsave); return cleanreturn(0, freelist); } return cleanreturn(1, freelist);} static voidseterror(int iarg, const char *msg, int *levels, const char *fname, const char *message){ char buf[512]; int i; char *p = buf; if (PyErr_Occurred()) return; else if (message == NULL) { if (fname != NULL) { PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname); p += strlen(p); } if (iarg != 0) { PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument %d", iarg); i = 0; p += strlen(p); while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { PyOS_snprintf(p, sizeof(buf) - (p - buf), ", item %d", levels[i]-1); p += strlen(p); i++; } } else { PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument"); p += strlen(p); } PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg); message = buf; } PyErr_SetString(PyExc_TypeError, message);} /* Convert a tuple argument. On entry, *p_format points to the character _after_ the opening '('. On successful exit, *p_format points to the closing ')'. If successful: *p_format and *p_va are updated, *levels and *msgbuf are untouched, and NULL is returned. If the argument is invalid: *p_format is unchanged, *p_va is undefined, *levels is a 0-terminated list of item numbers, *msgbuf contains an error message, whose format is: "must be <typename1>, not <typename2>", where: <typename1> is the name of the expected type, and <typename2> is the name of the actual type, and msgbuf is returned.*/ static char *converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *levels, char *msgbuf, size_t bufsize, int toplevel, PyObject **freelist){ int level = 0; int n = 0; const char *format = *p_format; int i; for (;;) { int c = *format++; if (c == '(') { if (level == 0) n++; level++; } else if (c == ')') { if (level == 0) break; level--; } else if (c == ':' || c == ';' || c == '\0') break; else if (level == 0 && isalpha(Py_CHARMASK(c))) n++; } if (!PySequence_Check(arg) || PyString_Check(arg)) { levels[0] = 0; PyOS_snprintf(msgbuf, bufsize, toplevel ? "expected %d arguments, not %.50s" : "must be %d-item sequence, not %.50s", n, arg == Py_None ? "None" : arg->ob_type->tp_name); return msgbuf; } if ((i = PySequence_Size(arg)) != n) { levels[0] = 0; PyOS_snprintf(msgbuf, bufsize, toplevel ? "expected %d arguments, not %d" : "must be sequence of length %d, not %d", n, i); return msgbuf; } format = *p_format; for (i = 0; i < n; i++) { char *msg; PyObject *item; item = PySequence_GetItem(arg, i); if (item == NULL) { PyErr_Clear(); levels[0] = i+1; levels[1] = 0; strncpy(msgbuf, "is not retrievable", bufsize); return msgbuf; } msg = convertitem(item, &format, p_va, flags, levels+1, msgbuf, bufsize, freelist); /* PySequence_GetItem calls tp->sq_item, which INCREFs */ Py_XDECREF(item); if (msg != NULL) { levels[0] = i+1; return msg; } } *p_format = format; return NULL;} /* Convert a single item. */ static char *convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *levels, char *msgbuf, size_t bufsize, PyObject **freelist){ char *msg; const char *format = *p_format; if (*format == '(' /* ')' */) { format++; msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, bufsize, 0, freelist); if (msg == NULL) format++; } else { msg = convertsimple(arg, &format, p_va, flags, msgbuf, bufsize, freelist); if (msg != NULL) levels[0] = 0; } if (msg == NULL) *p_format = format; return msg;} #define UNICODE_DEFAULT_ENCODING(arg) \ _PyUnicode_AsDefaultEncodedString(arg, NULL) /* Format an error message generated by convertsimple(). */ Lines 1–500 of 1771. Load more
/* New getargs implementation */ #include "Python.h" #include <ctype.h> #ifdef __cplusplus extern "C" { #endif int PyArg_Parse(PyObject *, const char *, ...); int PyArg_ParseTuple(PyObject *, const char *, ...); int PyArg_VaParse(PyObject *, const char *, va_list); int PyArg_ParseTupleAndKeywords(PyObject *, PyObject *, const char *, char **, ...); int PyArg_VaParseTupleAndKeywords(PyObject *, PyObject *, const char *, char **, va_list); #ifdef HAVE_DECLSPEC_DLL /* Export functions */ PyAPI_FUNC(int) _PyArg_Parse_SizeT(PyObject *, char *, ...); PyAPI_FUNC(int) _PyArg_ParseTuple_SizeT(PyObject *, char *, ...); PyAPI_FUNC(int) _PyArg_ParseTupleAndKeywords_SizeT(PyObject *, PyObject *, const char *, char **, ...); PyAPI_FUNC(PyObject *) _Py_BuildValue_SizeT(const char *, ...); PyAPI_FUNC(int) _PyArg_VaParse_SizeT(PyObject *, char *, va_list); PyAPI_FUNC(int) _PyArg_VaParseTupleAndKeywords_SizeT(PyObject *, PyObject *, const char *, char **, va_list); #endif #define FLAG_COMPAT 1 #define FLAG_SIZE_T 2 /* Forward */ static int vgetargs1(PyObject *, const char *, va_list *, int); static void seterror(int, const char *, int *, const char *, const char *); static char *convertitem(PyObject *, const char **, va_list *, int, int *, char *, size_t, PyObject **); static char *converttuple(PyObject *, const char **, va_list *, int, int *, char *, size_t, int, PyObject **); static char *convertsimple(PyObject *, const char **, va_list *, int, char *, size_t, PyObject **); static Py_ssize_t convertbuffer(PyObject *, void **p, char **); static int vgetargskeywords(PyObject *, PyObject *, const char *, char **, va_list *, int); static char *skipitem(const char **, va_list *, int); int PyArg_Parse(PyObject *args, const char *format, ...) { int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, FLAG_COMPAT); va_end(va); return retval; } int _PyArg_Parse_SizeT(PyObject *args, char *format, ...) { int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, FLAG_COMPAT|FLAG_SIZE_T); va_end(va); return retval; } int PyArg_ParseTuple(PyObject *args, const char *format, ...) { int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, 0); va_end(va); return retval; } int _PyArg_ParseTuple_SizeT(PyObject *args, char *format, ...) { int retval; va_list va; va_start(va, format); retval = vgetargs1(args, format, &va, FLAG_SIZE_T); va_end(va); return retval; } int PyArg_VaParse(PyObject *args, const char *format, va_list va) { va_list lva; #ifdef VA_LIST_IS_ARRAY memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy __va_copy(lva, va); #else lva = va; #endif #endif return vgetargs1(args, format, &lva, 0); } int _PyArg_VaParse_SizeT(PyObject *args, char *format, va_list va) { va_list lva; #ifdef VA_LIST_IS_ARRAY memcpy(lva, va, sizeof(va_list)); #else #ifdef __va_copy __va_copy(lva, va); #else lva = va; #endif #endif return vgetargs1(args, format, &lva, FLAG_SIZE_T); } /* Handle cleanup of allocated memory in case of exception */ static int addcleanup(void *ptr, PyObject **freelist) { PyObject *cobj; if (!*freelist) { *freelist = PyList_New(0); if (!*freelist) { PyMem_FREE(ptr); return -1; } } cobj = PyCObject_FromVoidPtr(ptr, NULL); if (!cobj) { PyMem_FREE(ptr); return -1; } if(PyList_Append(*freelist, cobj)) { PyMem_FREE(ptr); Py_DECREF(cobj); return -1; } Py_DECREF(cobj); return 0; } static int cleanreturn(int retval, PyObject *freelist) { if(freelist) { if((retval) == 0) { Py_ssize_t len = PyList_GET_SIZE(freelist), i; for (i = 0; i < len; i++) PyMem_FREE(PyCObject_AsVoidPtr( PyList_GET_ITEM(freelist, i))); } Py_DECREF(freelist); } return retval; } static int vgetargs1(PyObject *args, const char *format, va_list *p_va, int flags) { char msgbuf[256]; int levels[32]; const char *fname = NULL; const char *message = NULL; int min = -1; int max = 0; int level = 0; int endfmt = 0; const char *formatsave = format; Py_ssize_t i, len; char *msg; PyObject *freelist = NULL; int compat = flags & FLAG_COMPAT; assert(compat || (args != (PyObject*)NULL)); flags = flags & ~FLAG_COMPAT; while (endfmt == 0) { int c = *format++; switch (c) { case '(': if (level == 0) max++; level++; if (level >= 30) Py_FatalError("too many tuple nesting levels " "in argument format string"); break; case ')': if (level == 0) Py_FatalError("excess ')' in getargs format"); else level--; break; case '\0': endfmt = 1; break; case ':': fname = format; endfmt = 1; break; case ';': message = format; endfmt = 1; break; default: if (level == 0) { if (c == 'O') max++; else if (isalpha(Py_CHARMASK(c))) { if (c != 'e') /* skip encoded */ max++; } else if (c == '|') min = max; } break; } } if (level != 0) Py_FatalError(/* '(' */ "missing ')' in getargs format"); if (min < 0) min = max; format = formatsave; if (compat) { if (max == 0) { if (args == NULL) return 1; PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.200s%s takes no arguments", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); PyErr_SetString(PyExc_TypeError, msgbuf); return 0; } else if (min == 1 && max == 1) { if (args == NULL) { PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.200s%s takes at least one argument", fname==NULL ? "function" : fname, fname==NULL ? "" : "()"); PyErr_SetString(PyExc_TypeError, msgbuf); return 0; } msg = convertitem(args, &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg == NULL) return cleanreturn(1, freelist); seterror(levels[0], msg, levels+1, fname, message); return cleanreturn(0, freelist); } else { PyErr_SetString(PyExc_SystemError, "old style getargs format uses new features"); return 0; } } if (!PyTuple_Check(args)) { PyErr_SetString(PyExc_SystemError, "new style getargs format but argument is not a tuple"); return 0; } len = PyTuple_GET_SIZE(args); if (len < min || max < len) { if (message == NULL) { PyOS_snprintf(msgbuf, sizeof(msgbuf), "%.150s%s takes %s %d argument%s " "(%ld given)", fname==NULL ? "function" : fname, fname==NULL ? "" : "()", min==max ? "exactly" : len < min ? "at least" : "at most", len < min ? min : max, (len < min ? min : max) == 1 ? "" : "s", Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); message = msgbuf; } PyErr_SetString(PyExc_TypeError, message); return 0; } for (i = 0; i < len; i++) { if (*format == '|') format++; msg = convertitem(PyTuple_GET_ITEM(args, i), &format, p_va, flags, levels, msgbuf, sizeof(msgbuf), &freelist); if (msg) { seterror(i+1, msg, levels, fname, message); return cleanreturn(0, freelist); } } if (*format != '\0' && !isalpha(Py_CHARMASK(*format)) && *format != '(' && *format != '|' && *format != ':' && *format != ';') { PyErr_Format(PyExc_SystemError, "bad format string: %.200s", formatsave); return cleanreturn(0, freelist); } return cleanreturn(1, freelist); } static void seterror(int iarg, const char *msg, int *levels, const char *fname, const char *message) { char buf[512]; int i; char *p = buf; if (PyErr_Occurred()) return; else if (message == NULL) { if (fname != NULL) { PyOS_snprintf(p, sizeof(buf), "%.200s() ", fname); p += strlen(p); } if (iarg != 0) { PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument %d", iarg); i = 0; p += strlen(p); while (levels[i] > 0 && i < 32 && (int)(p-buf) < 220) { PyOS_snprintf(p, sizeof(buf) - (p - buf), ", item %d", levels[i]-1); p += strlen(p); i++; } } else { PyOS_snprintf(p, sizeof(buf) - (p - buf), "argument"); p += strlen(p); } PyOS_snprintf(p, sizeof(buf) - (p - buf), " %.256s", msg); message = buf; } PyErr_SetString(PyExc_TypeError, message); } /* Convert a tuple argument. On entry, *p_format points to the character _after_ the opening '('. On successful exit, *p_format points to the closing ')'. If successful: *p_format and *p_va are updated, *levels and *msgbuf are untouched, and NULL is returned. If the argument is invalid: *p_format is unchanged, *p_va is undefined, *levels is a 0-terminated list of item numbers, *msgbuf contains an error message, whose format is: "must be <typename1>, not <typename2>", where: <typename1> is the name of the expected type, and <typename2> is the name of the actual type, and msgbuf is returned. */ static char * converttuple(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *levels, char *msgbuf, size_t bufsize, int toplevel, PyObject **freelist) { int level = 0; int n = 0; const char *format = *p_format; int i; for (;;) { int c = *format++; if (c == '(') { if (level == 0) n++; level++; } else if (c == ')') { if (level == 0) break; level--; } else if (c == ':' || c == ';' || c == '\0') break; else if (level == 0 && isalpha(Py_CHARMASK(c))) n++; } if (!PySequence_Check(arg) || PyString_Check(arg)) { levels[0] = 0; PyOS_snprintf(msgbuf, bufsize, toplevel ? "expected %d arguments, not %.50s" : "must be %d-item sequence, not %.50s", n, arg == Py_None ? "None" : arg->ob_type->tp_name); return msgbuf; } if ((i = PySequence_Size(arg)) != n) { levels[0] = 0; PyOS_snprintf(msgbuf, bufsize, toplevel ? "expected %d arguments, not %d" : "must be sequence of length %d, not %d", n, i); return msgbuf; } format = *p_format; for (i = 0; i < n; i++) { char *msg; PyObject *item; item = PySequence_GetItem(arg, i); if (item == NULL) { PyErr_Clear(); levels[0] = i+1; levels[1] = 0; strncpy(msgbuf, "is not retrievable", bufsize); return msgbuf; } msg = convertitem(item, &format, p_va, flags, levels+1, msgbuf, bufsize, freelist); /* PySequence_GetItem calls tp->sq_item, which INCREFs */ Py_XDECREF(item); if (msg != NULL) { levels[0] = i+1; return msg; } } *p_format = format; return NULL; } /* Convert a single item. */ static char * convertitem(PyObject *arg, const char **p_format, va_list *p_va, int flags, int *levels, char *msgbuf, size_t bufsize, PyObject **freelist) { char *msg; const char *format = *p_format; if (*format == '(' /* ')' */) { format++; msg = converttuple(arg, &format, p_va, flags, levels, msgbuf, bufsize, 0, freelist); if (msg == NULL) format++; } else { msg = convertsimple(arg, &format, p_va, flags, msgbuf, bufsize, freelist); if (msg != NULL) levels[0] = 0; } if (msg == NULL) *p_format = format; return msg; } #define UNICODE_DEFAULT_ENCODING(arg) \ _PyUnicode_AsDefaultEncodedString(arg, NULL) /* Format an error message generated by convertsimple(). */