| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | #include "Python.h"
 | 
					
						
							| 
									
										
										
										
											2018-11-01 00:52:28 +01:00
										 |  |  | #include "pycore_state.h"
 | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | #include "frameobject.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 21:37:20 +01:00
										 |  |  | int | 
					
						
							|  |  |  | _PyObject_HasFastCall(PyObject *callable) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (PyFunction_Check(callable)) { | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyCFunction_Check(callable)) { | 
					
						
							|  |  |  |         return !(PyCFunction_GET_FLAGS(callable) & METH_VARARGS); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         assert (PyCallable_Check(callable)); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | static PyObject * | 
					
						
							|  |  |  | null_error(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!PyErr_Occurred()) | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_SystemError, | 
					
						
							|  |  |  |                         "null argument to internal routine"); | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							|  |  |  | _Py_CheckFunctionResult(PyObject *callable, PyObject *result, const char *where) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int err_occurred = (PyErr_Occurred() != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert((callable != NULL) ^ (where != NULL)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (result == NULL) { | 
					
						
							|  |  |  |         if (!err_occurred) { | 
					
						
							|  |  |  |             if (callable) | 
					
						
							|  |  |  |                 PyErr_Format(PyExc_SystemError, | 
					
						
							|  |  |  |                              "%R returned NULL without setting an error", | 
					
						
							|  |  |  |                              callable); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 PyErr_Format(PyExc_SystemError, | 
					
						
							|  |  |  |                              "%s returned NULL without setting an error", | 
					
						
							|  |  |  |                              where); | 
					
						
							|  |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  |             /* Ensure that the bug is caught in debug mode */ | 
					
						
							|  |  |  |             Py_FatalError("a function returned NULL without setting an error"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         if (err_occurred) { | 
					
						
							|  |  |  |             Py_DECREF(result); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (callable) { | 
					
						
							|  |  |  |                 _PyErr_FormatFromCause(PyExc_SystemError, | 
					
						
							|  |  |  |                         "%R returned a result with an error set", | 
					
						
							|  |  |  |                         callable); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 _PyErr_FormatFromCause(PyExc_SystemError, | 
					
						
							|  |  |  |                         "%s returned a result with an error set", | 
					
						
							|  |  |  |                         where); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  |             /* Ensure that the bug is caught in debug mode */ | 
					
						
							|  |  |  |             Py_FatalError("a function returned a result with an error set"); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- Core PyObject call functions ------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyObject_FastCallDict(PyObject *callable, PyObject *const *args, Py_ssize_t nargs, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                        PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* _PyObject_FastCallDict() must not be called with an exception set,
 | 
					
						
							|  |  |  |        because it can clear it (directly or indirectly) and so the | 
					
						
							|  |  |  |        caller loses its exception */ | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(callable != NULL); | 
					
						
							|  |  |  |     assert(nargs >= 0); | 
					
						
							|  |  |  |     assert(nargs == 0 || args != NULL); | 
					
						
							|  |  |  |     assert(kwargs == NULL || PyDict_Check(kwargs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyFunction_Check(callable)) { | 
					
						
							|  |  |  |         return _PyFunction_FastCallDict(callable, args, nargs, kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyCFunction_Check(callable)) { | 
					
						
							|  |  |  |         return _PyCFunction_FastCallDict(callable, args, nargs, kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         PyObject *argstuple, *result; | 
					
						
							|  |  |  |         ternaryfunc call; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Slow-path: build a temporary tuple */ | 
					
						
							|  |  |  |         call = callable->ob_type->tp_call; | 
					
						
							|  |  |  |         if (call == NULL) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", | 
					
						
							|  |  |  |                          callable->ob_type->tp_name); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         argstuple = _PyStack_AsTuple(args, nargs); | 
					
						
							|  |  |  |         if (argstuple == NULL) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Py_EnterRecursiveCall(" while calling a Python object")) { | 
					
						
							|  |  |  |             Py_DECREF(argstuple); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*call)(callable, argstuple, kwargs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  |         Py_DECREF(argstuple); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = _Py_CheckFunctionResult(callable, result, NULL); | 
					
						
							|  |  |  |         return result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyObject_FastCallKeywords(PyObject *callable, PyObject *const *stack, Py_ssize_t nargs, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                            PyObject *kwnames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* _PyObject_FastCallKeywords() must not be called with an exception set,
 | 
					
						
							|  |  |  |        because it can clear it (directly or indirectly) and so the | 
					
						
							|  |  |  |        caller loses its exception */ | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(nargs >= 0); | 
					
						
							|  |  |  |     assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* kwnames must only contains str strings, no subclass, and all keys must
 | 
					
						
							|  |  |  |        be unique: these checks are implemented in Python/ceval.c and | 
					
						
							|  |  |  |        _PyArg_ParseStackAndKeywords(). */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyFunction_Check(callable)) { | 
					
						
							|  |  |  |         return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyCFunction_Check(callable)) { | 
					
						
							|  |  |  |         return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         /* Slow-path: build a temporary tuple for positional arguments and a
 | 
					
						
							|  |  |  |            temporary dictionary for keyword arguments (if any) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ternaryfunc call; | 
					
						
							|  |  |  |         PyObject *argstuple; | 
					
						
							|  |  |  |         PyObject *kwdict, *result; | 
					
						
							|  |  |  |         Py_ssize_t nkwargs; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); | 
					
						
							|  |  |  |         assert((nargs == 0 && nkwargs == 0) || stack != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         call = callable->ob_type->tp_call; | 
					
						
							|  |  |  |         if (call == NULL) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", | 
					
						
							|  |  |  |                          callable->ob_type->tp_name); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         argstuple = _PyStack_AsTuple(stack, nargs); | 
					
						
							|  |  |  |         if (argstuple == NULL) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (nkwargs > 0) { | 
					
						
							|  |  |  |             kwdict = _PyStack_AsDict(stack + nargs, kwnames); | 
					
						
							|  |  |  |             if (kwdict == NULL) { | 
					
						
							|  |  |  |                 Py_DECREF(argstuple); | 
					
						
							|  |  |  |                 return NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             kwdict = NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Py_EnterRecursiveCall(" while calling a Python object")) { | 
					
						
							|  |  |  |             Py_DECREF(argstuple); | 
					
						
							|  |  |  |             Py_XDECREF(kwdict); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*call)(callable, argstuple, kwdict); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_DECREF(argstuple); | 
					
						
							|  |  |  |         Py_XDECREF(kwdict); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = _Py_CheckFunctionResult(callable, result, NULL); | 
					
						
							|  |  |  |         return result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ternaryfunc call; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* PyObject_Call() must not be called with an exception set,
 | 
					
						
							|  |  |  |        because it can clear it (directly or indirectly) and so the | 
					
						
							|  |  |  |        caller loses its exception */ | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  |     assert(PyTuple_Check(args)); | 
					
						
							|  |  |  |     assert(kwargs == NULL || PyDict_Check(kwargs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyFunction_Check(callable)) { | 
					
						
							|  |  |  |         return _PyFunction_FastCallDict(callable, | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |                                         _PyTuple_ITEMS(args), | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                                         PyTuple_GET_SIZE(args), | 
					
						
							|  |  |  |                                         kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (PyCFunction_Check(callable)) { | 
					
						
							|  |  |  |         return PyCFunction_Call(callable, args, kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         call = callable->ob_type->tp_call; | 
					
						
							|  |  |  |         if (call == NULL) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", | 
					
						
							|  |  |  |                          callable->ob_type->tp_name); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Py_EnterRecursiveCall(" while calling a Python object")) | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*call)(callable, args, kwargs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return _Py_CheckFunctionResult(callable, result, NULL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- PyFunction call functions ---------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject* _Py_HOT_FUNCTION | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | function_code_fastcall(PyCodeObject *co, PyObject *const *args, Py_ssize_t nargs, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                        PyObject *globals) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyFrameObject *f; | 
					
						
							| 
									
										
										
										
											2018-11-01 01:51:40 +01:00
										 |  |  |     PyThreadState *tstate = _PyThreadState_GET(); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     PyObject **fastlocals; | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(globals != NULL); | 
					
						
							|  |  |  |     /* XXX Perhaps we should create a specialized
 | 
					
						
							|  |  |  |        _PyFrame_New_NoTrack() that doesn't take locals, but does | 
					
						
							|  |  |  |        take builtins without sanity checking them. | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |     assert(tstate != NULL); | 
					
						
							|  |  |  |     f = _PyFrame_New_NoTrack(tstate, co, globals, NULL); | 
					
						
							|  |  |  |     if (f == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     fastlocals = f->f_localsplus; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nargs; i++) { | 
					
						
							|  |  |  |         Py_INCREF(*args); | 
					
						
							|  |  |  |         fastlocals[i] = *args++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     result = PyEval_EvalFrameEx(f,0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (Py_REFCNT(f) > 1) { | 
					
						
							|  |  |  |         Py_DECREF(f); | 
					
						
							|  |  |  |         _PyObject_GC_TRACK(f); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         ++tstate->recursion_depth; | 
					
						
							|  |  |  |         Py_DECREF(f); | 
					
						
							|  |  |  |         --tstate->recursion_depth; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyFunction_FastCallDict(PyObject *func, PyObject *const *args, Py_ssize_t nargs, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                          PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); | 
					
						
							|  |  |  |     PyObject *globals = PyFunction_GET_GLOBALS(func); | 
					
						
							|  |  |  |     PyObject *argdefs = PyFunction_GET_DEFAULTS(func); | 
					
						
							|  |  |  |     PyObject *kwdefs, *closure, *name, *qualname; | 
					
						
							|  |  |  |     PyObject *kwtuple, **k; | 
					
						
							|  |  |  |     PyObject **d; | 
					
						
							|  |  |  |     Py_ssize_t nd, nk; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(func != NULL); | 
					
						
							|  |  |  |     assert(nargs >= 0); | 
					
						
							|  |  |  |     assert(nargs == 0 || args != NULL); | 
					
						
							|  |  |  |     assert(kwargs == NULL || PyDict_Check(kwargs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (co->co_kwonlyargcount == 0 && | 
					
						
							|  |  |  |         (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) && | 
					
						
							| 
									
										
										
										
											2017-10-25 05:26:17 -07:00
										 |  |  |         (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         /* Fast paths */ | 
					
						
							|  |  |  |         if (argdefs == NULL && co->co_argcount == nargs) { | 
					
						
							|  |  |  |             return function_code_fastcall(co, args, nargs, globals); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (nargs == 0 && argdefs != NULL | 
					
						
							| 
									
										
										
										
											2017-03-21 08:53:25 +02:00
										 |  |  |                  && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |             /* function called with no arguments, but all parameters have
 | 
					
						
							|  |  |  |                a default value: use default values as arguments .*/ | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |             args = _PyTuple_ITEMS(argdefs); | 
					
						
							| 
									
										
										
										
											2017-03-21 08:53:25 +02:00
										 |  |  |             return function_code_fastcall(co, args, PyTuple_GET_SIZE(argdefs), | 
					
						
							|  |  |  |                                           globals); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nk = (kwargs != NULL) ? PyDict_GET_SIZE(kwargs) : 0; | 
					
						
							|  |  |  |     if (nk != 0) { | 
					
						
							|  |  |  |         Py_ssize_t pos, i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 18:26:43 +01:00
										 |  |  |         /* bpo-29318, bpo-27840: Caller and callee functions must not share
 | 
					
						
							|  |  |  |            the dictionary: kwargs must be copied. */ | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         kwtuple = PyTuple_New(2 * nk); | 
					
						
							|  |  |  |         if (kwtuple == NULL) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |         k = _PyTuple_ITEMS(kwtuple); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         pos = i = 0; | 
					
						
							|  |  |  |         while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { | 
					
						
							|  |  |  |             /* We must hold strong references because keyword arguments can be
 | 
					
						
							|  |  |  |                indirectly modified while the function is called: | 
					
						
							|  |  |  |                see issue #2016 and test_extcall */ | 
					
						
							|  |  |  |             Py_INCREF(k[i]); | 
					
						
							|  |  |  |             Py_INCREF(k[i+1]); | 
					
						
							|  |  |  |             i += 2; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-10-22 08:52:46 -07:00
										 |  |  |         assert(i / 2 == nk); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         kwtuple = NULL; | 
					
						
							|  |  |  |         k = NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kwdefs = PyFunction_GET_KW_DEFAULTS(func); | 
					
						
							|  |  |  |     closure = PyFunction_GET_CLOSURE(func); | 
					
						
							|  |  |  |     name = ((PyFunctionObject *)func) -> func_name; | 
					
						
							|  |  |  |     qualname = ((PyFunctionObject *)func) -> func_qualname; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (argdefs != NULL) { | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |         d = _PyTuple_ITEMS(argdefs); | 
					
						
							| 
									
										
										
										
											2017-03-21 08:53:25 +02:00
										 |  |  |         nd = PyTuple_GET_SIZE(argdefs); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         d = NULL; | 
					
						
							|  |  |  |         nd = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL, | 
					
						
							|  |  |  |                                       args, nargs, | 
					
						
							| 
									
										
										
										
											2017-07-31 08:24:37 -06:00
										 |  |  |                                       k, k != NULL ? k + 1 : NULL, nk, 2, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                                       d, nd, kwdefs, | 
					
						
							|  |  |  |                                       closure, name, qualname); | 
					
						
							|  |  |  |     Py_XDECREF(kwtuple); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyFunction_FastCallKeywords(PyObject *func, PyObject *const *stack, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                              Py_ssize_t nargs, PyObject *kwnames) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); | 
					
						
							|  |  |  |     PyObject *globals = PyFunction_GET_GLOBALS(func); | 
					
						
							|  |  |  |     PyObject *argdefs = PyFunction_GET_DEFAULTS(func); | 
					
						
							|  |  |  |     PyObject *kwdefs, *closure, *name, *qualname; | 
					
						
							|  |  |  |     PyObject **d; | 
					
						
							|  |  |  |     Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); | 
					
						
							|  |  |  |     Py_ssize_t nd; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(PyFunction_Check(func)); | 
					
						
							|  |  |  |     assert(nargs >= 0); | 
					
						
							|  |  |  |     assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); | 
					
						
							|  |  |  |     assert((nargs == 0 && nkwargs == 0) || stack != NULL); | 
					
						
							|  |  |  |     /* kwnames must only contains str strings, no subclass, and all keys must
 | 
					
						
							|  |  |  |        be unique */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (co->co_kwonlyargcount == 0 && nkwargs == 0 && | 
					
						
							| 
									
										
										
										
											2017-10-25 05:26:17 -07:00
										 |  |  |         (co->co_flags & ~PyCF_MASK) == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (argdefs == NULL && co->co_argcount == nargs) { | 
					
						
							|  |  |  |             return function_code_fastcall(co, stack, nargs, globals); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (nargs == 0 && argdefs != NULL | 
					
						
							| 
									
										
										
										
											2017-03-21 08:53:25 +02:00
										 |  |  |                  && co->co_argcount == PyTuple_GET_SIZE(argdefs)) { | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |             /* function called with no arguments, but all parameters have
 | 
					
						
							|  |  |  |                a default value: use default values as arguments .*/ | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |             stack = _PyTuple_ITEMS(argdefs); | 
					
						
							| 
									
										
										
										
											2017-03-21 08:53:25 +02:00
										 |  |  |             return function_code_fastcall(co, stack, PyTuple_GET_SIZE(argdefs), | 
					
						
							|  |  |  |                                           globals); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kwdefs = PyFunction_GET_KW_DEFAULTS(func); | 
					
						
							|  |  |  |     closure = PyFunction_GET_CLOSURE(func); | 
					
						
							|  |  |  |     name = ((PyFunctionObject *)func) -> func_name; | 
					
						
							|  |  |  |     qualname = ((PyFunctionObject *)func) -> func_qualname; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (argdefs != NULL) { | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |         d = _PyTuple_ITEMS(argdefs); | 
					
						
							| 
									
										
										
										
											2017-03-21 08:53:25 +02:00
										 |  |  |         nd = PyTuple_GET_SIZE(argdefs); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         d = NULL; | 
					
						
							|  |  |  |         nd = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return _PyEval_EvalCodeWithName((PyObject*)co, globals, (PyObject *)NULL, | 
					
						
							|  |  |  |                                     stack, nargs, | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |                                     nkwargs ? _PyTuple_ITEMS(kwnames) : NULL, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                                     stack + nargs, | 
					
						
							|  |  |  |                                     nkwargs, 1, | 
					
						
							|  |  |  |                                     d, (int)nd, kwdefs, | 
					
						
							|  |  |  |                                     closure, name, qualname); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- PyCFunction call functions --------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, | 
					
						
							|  |  |  |                              PyObject *const *args, Py_ssize_t nargs, | 
					
						
							|  |  |  |                              PyObject *kwargs) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     /* _PyMethodDef_RawFastCallDict() must not be called with an exception set,
 | 
					
						
							|  |  |  |        because it can clear it (directly or indirectly) and so the | 
					
						
							|  |  |  |        caller loses its exception */ | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(method != NULL); | 
					
						
							|  |  |  |     assert(nargs >= 0); | 
					
						
							|  |  |  |     assert(nargs == 0 || args != NULL); | 
					
						
							|  |  |  |     assert(kwargs == NULL || PyDict_Check(kwargs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyCFunction meth = method->ml_meth; | 
					
						
							|  |  |  |     int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); | 
					
						
							|  |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (Py_EnterRecursiveCall(" while calling a Python object")) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (flags) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case METH_NOARGS: | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |         if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { | 
					
						
							|  |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         if (nargs != 0) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                 "%.200s() takes no arguments (%zd given)", | 
					
						
							|  |  |  |                 method->ml_name, nargs); | 
					
						
							|  |  |  |             goto exit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*meth) (self, NULL); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_O: | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |         if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { | 
					
						
							|  |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         if (nargs != 1) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                 "%.200s() takes exactly one argument (%zd given)", | 
					
						
							|  |  |  |                 method->ml_name, nargs); | 
					
						
							|  |  |  |             goto exit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*meth) (self, args[0]); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_VARARGS: | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |         if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-08-21 13:09:59 +02:00
										 |  |  |         /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case METH_VARARGS | METH_KEYWORDS: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /* Slow-path: create a temporary tuple for positional arguments */ | 
					
						
							|  |  |  |         PyObject *argstuple = _PyStack_AsTuple(args, nargs); | 
					
						
							|  |  |  |         if (argstuple == NULL) { | 
					
						
							|  |  |  |             goto exit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (flags & METH_KEYWORDS) { | 
					
						
							|  |  |  |             result = (*(PyCFunctionWithKeywords)meth) (self, argstuple, kwargs); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             result = (*meth) (self, argstuple); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(argstuple); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_FASTCALL: | 
					
						
							| 
									
										
										
										
											2017-07-03 21:20:15 +03:00
										 |  |  |     { | 
					
						
							|  |  |  |         if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { | 
					
						
							|  |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*(_PyCFunctionFast)meth) (self, args, nargs); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_FASTCALL | METH_KEYWORDS: | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  |         PyObject *const *stack; | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         PyObject *kwnames; | 
					
						
							| 
									
										
										
										
											2017-07-03 21:20:15 +03:00
										 |  |  |         _PyCFunctionFastWithKeywords fastmeth = (_PyCFunctionFastWithKeywords)meth; | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) { | 
					
						
							|  |  |  |             goto exit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*fastmeth) (self, stack, nargs, kwnames); | 
					
						
							|  |  |  |         if (stack != args) { | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  |             PyMem_Free((PyObject **)stack); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         Py_XDECREF(kwnames); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_SystemError, | 
					
						
							|  |  |  |                         "Bad call flags in _PyMethodDef_RawFastCallDict. " | 
					
						
							|  |  |  |                         "METH_OLDARGS is no longer supported!"); | 
					
						
							|  |  |  |         goto exit; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     goto exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | no_keyword_error: | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                  "%.200s() takes no keyword arguments", | 
					
						
							| 
									
										
										
										
											2017-03-27 23:36:08 +02:00
										 |  |  |                  method->ml_name); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | exit: | 
					
						
							|  |  |  |     Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyCFunction_FastCallDict(PyObject *func, | 
					
						
							|  |  |  |                           PyObject *const *args, Py_ssize_t nargs, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                           PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(func != NULL); | 
					
						
							|  |  |  |     assert(PyCFunction_Check(func)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = _PyMethodDef_RawFastCallDict(((PyCFunctionObject*)func)->m_ml, | 
					
						
							|  |  |  |                                           PyCFunction_GET_SELF(func), | 
					
						
							|  |  |  |                                           args, nargs, kwargs); | 
					
						
							|  |  |  |     result = _Py_CheckFunctionResult(func, result, NULL); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, | 
					
						
							|  |  |  |                                  PyObject *const *args, Py_ssize_t nargs, | 
					
						
							|  |  |  |                                  PyObject *kwnames) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     /* _PyMethodDef_RawFastCallKeywords() must not be called with an exception set,
 | 
					
						
							|  |  |  |        because it can clear it (directly or indirectly) and so the | 
					
						
							|  |  |  |        caller loses its exception */ | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(method != NULL); | 
					
						
							|  |  |  |     assert(nargs >= 0); | 
					
						
							|  |  |  |     assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); | 
					
						
							|  |  |  |     /* kwnames must only contains str strings, no subclass, and all keys must
 | 
					
						
							|  |  |  |        be unique */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     PyCFunction meth = method->ml_meth; | 
					
						
							|  |  |  |     int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST); | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |     Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_GET_SIZE(kwnames); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     PyObject *result = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (Py_EnterRecursiveCall(" while calling a Python object")) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     switch (flags) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     case METH_NOARGS: | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |         if (nkwargs) { | 
					
						
							|  |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         if (nargs != 0) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                 "%.200s() takes no arguments (%zd given)", | 
					
						
							|  |  |  |                 method->ml_name, nargs); | 
					
						
							|  |  |  |             goto exit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*meth) (self, NULL); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_O: | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |         if (nkwargs) { | 
					
						
							|  |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         if (nargs != 1) { | 
					
						
							|  |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                 "%.200s() takes exactly one argument (%zd given)", | 
					
						
							|  |  |  |                 method->ml_name, nargs); | 
					
						
							|  |  |  |             goto exit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*meth) (self, args[0]); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_FASTCALL: | 
					
						
							| 
									
										
										
										
											2017-07-03 21:20:15 +03:00
										 |  |  |         if (nkwargs) { | 
					
						
							|  |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         result = ((_PyCFunctionFast)meth) (self, args, nargs); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_FASTCALL | METH_KEYWORDS: | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         /* Fast-path: avoid temporary dict to pass keyword arguments */ | 
					
						
							| 
									
										
										
										
											2017-07-03 21:20:15 +03:00
										 |  |  |         result = ((_PyCFunctionFastWithKeywords)meth) (self, args, nargs, kwnames); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case METH_VARARGS: | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |         if (nkwargs) { | 
					
						
							|  |  |  |             goto no_keyword_error; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-08-21 13:09:59 +02:00
										 |  |  |         /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |     case METH_VARARGS | METH_KEYWORDS: | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         /* Slow-path: create a temporary tuple for positional arguments
 | 
					
						
							|  |  |  |            and a temporary dict for keyword arguments */ | 
					
						
							|  |  |  |         PyObject *argtuple; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         argtuple = _PyStack_AsTuple(args, nargs); | 
					
						
							|  |  |  |         if (argtuple == NULL) { | 
					
						
							|  |  |  |             goto exit; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (flags & METH_KEYWORDS) { | 
					
						
							|  |  |  |             PyObject *kwdict; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (nkwargs > 0) { | 
					
						
							|  |  |  |                 kwdict = _PyStack_AsDict(args + nargs, kwnames); | 
					
						
							|  |  |  |                 if (kwdict == NULL) { | 
					
						
							|  |  |  |                     Py_DECREF(argtuple); | 
					
						
							|  |  |  |                     goto exit; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 kwdict = NULL; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             result = (*(PyCFunctionWithKeywords)meth) (self, argtuple, kwdict); | 
					
						
							|  |  |  |             Py_XDECREF(kwdict); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             result = (*meth) (self, argtuple); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         Py_DECREF(argtuple); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_SystemError, | 
					
						
							|  |  |  |                         "Bad call flags in _PyCFunction_FastCallKeywords. " | 
					
						
							|  |  |  |                         "METH_OLDARGS is no longer supported!"); | 
					
						
							|  |  |  |         goto exit; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     goto exit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | no_keyword_error: | 
					
						
							|  |  |  |     PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                  "%.200s() takes no keyword arguments", | 
					
						
							|  |  |  |                  method->ml_name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exit: | 
					
						
							|  |  |  |     Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyCFunction_FastCallKeywords(PyObject *func, | 
					
						
							|  |  |  |                               PyObject *const *args, Py_ssize_t nargs, | 
					
						
							|  |  |  |                               PyObject *kwnames) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(func != NULL); | 
					
						
							|  |  |  |     assert(PyCFunction_Check(func)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     result = _PyMethodDef_RawFastCallKeywords(((PyCFunctionObject*)func)->m_ml, | 
					
						
							|  |  |  |                                               PyCFunction_GET_SELF(func), | 
					
						
							|  |  |  |                                               args, nargs, kwnames); | 
					
						
							|  |  |  |     result = _Py_CheckFunctionResult(func, result, NULL); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |     assert(kwargs == NULL || PyDict_Check(kwargs)); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     PyCFunction meth = PyCFunction_GET_FUNCTION(func); | 
					
						
							|  |  |  |     PyObject *self = PyCFunction_GET_SELF(func); | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyCFunction_GET_FLAGS(func) & METH_KEYWORDS) { | 
					
						
							|  |  |  |         if (Py_EnterRecursiveCall(" while calling a Python object")) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*(PyCFunctionWithKeywords)meth)(self, args, kwargs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2017-06-06 18:45:22 +03:00
										 |  |  |         if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |             PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", | 
					
						
							|  |  |  |                          ((PyCFunctionObject*)func)->m_ml->ml_name); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (Py_EnterRecursiveCall(" while calling a Python object")) { | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         result = (*meth)(self, args); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Py_LeaveRecursiveCall(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return _Py_CheckFunctionResult(func, result, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* first try METH_VARARGS to pass directly args tuple unchanged.
 | 
					
						
							|  |  |  |        _PyMethodDef_RawFastCallDict() creates a new temporary tuple | 
					
						
							|  |  |  |        for METH_VARARGS. */ | 
					
						
							|  |  |  |     if (PyCFunction_GET_FLAGS(func) & METH_VARARGS) { | 
					
						
							|  |  |  |         return cfunction_call_varargs(func, args, kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         return _PyCFunction_FastCallDict(func, | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |                                          _PyTuple_ITEMS(args), | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                                          PyTuple_GET_SIZE(args), | 
					
						
							|  |  |  |                                          kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- More complex call functions -------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* External interface to call any callable object.
 | 
					
						
							|  |  |  |    The args must be a tuple or NULL.  The kwargs must be a dict or NULL. */ | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyEval_CallObjectWithKeywords(PyObject *callable, | 
					
						
							|  |  |  |                               PyObject *args, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef Py_DEBUG
 | 
					
						
							|  |  |  |     /* PyEval_CallObjectWithKeywords() must not be called with an exception
 | 
					
						
							|  |  |  |        set. It raises a new exception if parameters are invalid or if | 
					
						
							|  |  |  |        PyTuple_New() fails, and so the original exception is lost. */ | 
					
						
							|  |  |  |     assert(!PyErr_Occurred()); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-01 20:41:03 +09:00
										 |  |  |     if (args != NULL && !PyTuple_Check(args)) { | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "argument list must be a tuple"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (kwargs != NULL && !PyDict_Check(kwargs)) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, | 
					
						
							|  |  |  |                         "keyword list must be a dictionary"); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-01 20:41:03 +09:00
										 |  |  |     if (args == NULL) { | 
					
						
							|  |  |  |         return _PyObject_FastCallDict(callable, NULL, 0, kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         return PyObject_Call(callable, args, kwargs); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyObject_CallObject(PyObject *callable, PyObject *args) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return PyEval_CallObjectWithKeywords(callable, args, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Positional arguments are obj followed by args:
 | 
					
						
							|  |  |  |    call callable(obj, *args, **kwargs) */ | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyObject_FastCall_Prepend(PyObject *callable, PyObject *obj, | 
					
						
							|  |  |  |                            PyObject *const *args, Py_ssize_t nargs) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; | 
					
						
							|  |  |  |     PyObject **args2; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nargs++; | 
					
						
							|  |  |  |     if (nargs <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { | 
					
						
							|  |  |  |         args2 = small_stack; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         args2 = PyMem_Malloc(nargs * sizeof(PyObject *)); | 
					
						
							|  |  |  |         if (args2 == NULL) { | 
					
						
							|  |  |  |             PyErr_NoMemory(); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* use borrowed references */ | 
					
						
							|  |  |  |     args2[0] = obj; | 
					
						
							| 
									
										
										
										
											2017-09-04 22:23:42 -07:00
										 |  |  |     if (nargs > 1) { | 
					
						
							|  |  |  |         memcpy(&args2[1], args, (nargs - 1) * sizeof(PyObject *)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     result = _PyObject_FastCall(callable, args2, nargs); | 
					
						
							|  |  |  |     if (args2 != small_stack) { | 
					
						
							|  |  |  |         PyMem_Free(args2); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Call callable(obj, *args, **kwargs). */ | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyObject_Call_Prepend(PyObject *callable, | 
					
						
							|  |  |  |                        PyObject *obj, PyObject *args, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; | 
					
						
							|  |  |  |     PyObject **stack; | 
					
						
							|  |  |  |     Py_ssize_t argcount; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(PyTuple_Check(args)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     argcount = PyTuple_GET_SIZE(args); | 
					
						
							|  |  |  |     if (argcount + 1 <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { | 
					
						
							|  |  |  |         stack = small_stack; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         stack = PyMem_Malloc((argcount + 1) * sizeof(PyObject *)); | 
					
						
							|  |  |  |         if (stack == NULL) { | 
					
						
							|  |  |  |             PyErr_NoMemory(); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* use borrowed references */ | 
					
						
							|  |  |  |     stack[0] = obj; | 
					
						
							|  |  |  |     memcpy(&stack[1], | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |            _PyTuple_ITEMS(args), | 
					
						
							|  |  |  |            argcount * sizeof(PyObject *)); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     result = _PyObject_FastCallDict(callable, | 
					
						
							|  |  |  |                                     stack, argcount + 1, | 
					
						
							|  |  |  |                                     kwargs); | 
					
						
							|  |  |  |     if (stack != small_stack) { | 
					
						
							|  |  |  |         PyMem_Free(stack); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- Call with a format string ---------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | _PyObject_CallFunctionVa(PyObject *callable, const char *format, | 
					
						
							|  |  |  |                          va_list va, int is_size_t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject* small_stack[_PY_FASTCALL_SMALL_STACK]; | 
					
						
							|  |  |  |     const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack); | 
					
						
							|  |  |  |     PyObject **stack; | 
					
						
							|  |  |  |     Py_ssize_t nargs, i; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (callable == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!format || !*format) { | 
					
						
							|  |  |  |         return _PyObject_CallNoArg(callable); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_size_t) { | 
					
						
							|  |  |  |         stack = _Py_VaBuildStack_SizeT(small_stack, small_stack_len, | 
					
						
							|  |  |  |                                        format, va, &nargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         stack = _Py_VaBuildStack(small_stack, small_stack_len, | 
					
						
							|  |  |  |                                  format, va, &nargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (stack == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (nargs == 1 && PyTuple_Check(stack[0])) { | 
					
						
							|  |  |  |         /* Special cases for backward compatibility:
 | 
					
						
							|  |  |  |            - PyObject_CallFunction(func, "O", tuple) calls func(*tuple) | 
					
						
							|  |  |  |            - PyObject_CallFunction(func, "(OOO)", arg1, arg2, arg3) calls | 
					
						
							|  |  |  |              func(*(arg1, arg2, arg3)): func(arg1, arg2, arg3) */ | 
					
						
							|  |  |  |         PyObject *args = stack[0]; | 
					
						
							|  |  |  |         result = _PyObject_FastCall(callable, | 
					
						
							| 
									
										
										
										
											2018-11-09 16:56:48 +01:00
										 |  |  |                                     _PyTuple_ITEMS(args), | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                                     PyTuple_GET_SIZE(args)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         result = _PyObject_FastCall(callable, stack, nargs); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nargs; ++i) { | 
					
						
							|  |  |  |         Py_DECREF(stack[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (stack != small_stack) { | 
					
						
							|  |  |  |         PyMem_Free(stack); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyObject_CallFunction(PyObject *callable, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     result = _PyObject_CallFunctionVa(callable, format, va, 0); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  | /* PyEval_CallFunction is exact copy of PyObject_CallFunction.
 | 
					
						
							|  |  |  |  * This function is kept for backward compatibility. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | PyEval_CallFunction(PyObject *callable, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     result = _PyObject_CallFunctionVa(callable, format, va, 0); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyObject_CallFunction_SizeT(PyObject *callable, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     result = _PyObject_CallFunctionVa(callable, format, va, 1); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject* | 
					
						
							|  |  |  | callmethod(PyObject* callable, const char *format, va_list va, int is_size_t) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     assert(callable != NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!PyCallable_Check(callable)) { | 
					
						
							|  |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                      "attribute of type '%.200s' is not callable", | 
					
						
							|  |  |  |                      Py_TYPE(callable)->tp_name); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return _PyObject_CallFunctionVa(callable, format, va, is_size_t); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *callable, *retval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (obj == NULL || name == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     callable = PyObject_GetAttrString(obj, name); | 
					
						
							|  |  |  |     if (callable == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     retval = callmethod(callable, format, va, 0); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(callable); | 
					
						
							|  |  |  |     return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  | /* PyEval_CallMethod is exact copy of PyObject_CallMethod.
 | 
					
						
							|  |  |  |  * This function is kept for backward compatibility. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | PyObject * | 
					
						
							|  |  |  | PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *callable, *retval; | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     if (obj == NULL || name == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     callable = PyObject_GetAttrString(obj, name); | 
					
						
							|  |  |  |     if (callable == NULL) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     retval = callmethod(callable, format, va, 0); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-14 18:00:59 +09:00
										 |  |  |     Py_DECREF(callable); | 
					
						
							|  |  |  |     return retval; | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyObject_CallMethodId(PyObject *obj, _Py_Identifier *name, | 
					
						
							|  |  |  |                        const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *callable, *retval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (obj == NULL || name == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     callable = _PyObject_GetAttrId(obj, name); | 
					
						
							|  |  |  |     if (callable == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     retval = callmethod(callable, format, va, 0); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(callable); | 
					
						
							|  |  |  |     return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyObject_CallMethod_SizeT(PyObject *obj, const char *name, | 
					
						
							|  |  |  |                            const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *callable, *retval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (obj == NULL || name == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     callable = PyObject_GetAttrString(obj, name); | 
					
						
							|  |  |  |     if (callable == NULL) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     retval = callmethod(callable, format, va, 1); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(callable); | 
					
						
							|  |  |  |     return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, | 
					
						
							|  |  |  |                              const char *format, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list va; | 
					
						
							|  |  |  |     PyObject *callable, *retval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (obj == NULL || name == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     callable = _PyObject_GetAttrId(obj, name); | 
					
						
							|  |  |  |     if (callable == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(va, format); | 
					
						
							|  |  |  |     retval = callmethod(callable, format, va, 1); | 
					
						
							|  |  |  |     va_end(va); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(callable); | 
					
						
							|  |  |  |     return retval; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- Call with "..." arguments ---------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | object_vacall(PyObject *callable, va_list vargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; | 
					
						
							|  |  |  |     PyObject **stack; | 
					
						
							|  |  |  |     Py_ssize_t nargs; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  |     va_list countva; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (callable == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Count the number of arguments */ | 
					
						
							|  |  |  |     va_copy(countva, vargs); | 
					
						
							|  |  |  |     nargs = 0; | 
					
						
							|  |  |  |     while (1) { | 
					
						
							|  |  |  |         PyObject *arg = va_arg(countva, PyObject *); | 
					
						
							|  |  |  |         if (arg == NULL) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         nargs++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     va_end(countva); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Copy arguments */ | 
					
						
							|  |  |  |     if (nargs <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { | 
					
						
							|  |  |  |         stack = small_stack; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         stack = PyMem_Malloc(nargs * sizeof(stack[0])); | 
					
						
							|  |  |  |         if (stack == NULL) { | 
					
						
							|  |  |  |             PyErr_NoMemory(); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nargs; ++i) { | 
					
						
							|  |  |  |         stack[i] = va_arg(vargs, PyObject *); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Call the function */ | 
					
						
							|  |  |  |     result = _PyObject_FastCall(callable, stack, nargs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (stack != small_stack) { | 
					
						
							|  |  |  |         PyMem_Free(stack); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list vargs; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (callable == NULL || name == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     callable = PyObject_GetAttr(callable, name); | 
					
						
							|  |  |  |     if (callable == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(vargs, name); | 
					
						
							|  |  |  |     result = object_vacall(callable, vargs); | 
					
						
							|  |  |  |     va_end(vargs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(callable); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | _PyObject_CallMethodIdObjArgs(PyObject *obj, | 
					
						
							|  |  |  |                               struct _Py_Identifier *name, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list vargs; | 
					
						
							|  |  |  |     PyObject *callable, *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (obj == NULL || name == NULL) { | 
					
						
							|  |  |  |         return null_error(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     callable = _PyObject_GetAttrId(obj, name); | 
					
						
							|  |  |  |     if (callable == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(vargs, name); | 
					
						
							|  |  |  |     result = object_vacall(callable, vargs); | 
					
						
							|  |  |  |     va_end(vargs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Py_DECREF(callable); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyObject_CallFunctionObjArgs(PyObject *callable, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     va_list vargs; | 
					
						
							|  |  |  |     PyObject *result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     va_start(vargs, callable); | 
					
						
							|  |  |  |     result = object_vacall(callable, vargs); | 
					
						
							|  |  |  |     va_end(vargs); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* --- PyStack functions ------------------------------------------ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Issue #29234: Inlining _PyStack_AsTuple() into callers increases their
 | 
					
						
							|  |  |  |    stack consumption, Disable inlining to optimize the stack consumption. */ | 
					
						
							| 
									
										
										
										
											2018-07-24 10:55:47 +03:00
										 |  |  | _Py_NO_INLINE PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyStack_AsTuple(PyObject *const *stack, Py_ssize_t nargs) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject *args; | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     args = PyTuple_New(nargs); | 
					
						
							|  |  |  |     if (args == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i=0; i < nargs; i++) { | 
					
						
							|  |  |  |         PyObject *item = stack[i]; | 
					
						
							|  |  |  |         Py_INCREF(item); | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(args, i, item); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return args; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject* | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyStack_AsTupleSlice(PyObject *const *stack, Py_ssize_t nargs, | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  |                       Py_ssize_t start, Py_ssize_t end) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *args; | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(0 <= start); | 
					
						
							|  |  |  |     assert(end <= nargs); | 
					
						
							|  |  |  |     assert(start <= end); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     args = PyTuple_New(end - start); | 
					
						
							|  |  |  |     if (args == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i=start; i < end; i++) { | 
					
						
							|  |  |  |         PyObject *item = stack[i]; | 
					
						
							|  |  |  |         Py_INCREF(item); | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(args, i - start, item); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return args; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyStack_AsDict(PyObject *const *values, PyObject *kwnames) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     Py_ssize_t nkwargs; | 
					
						
							|  |  |  |     PyObject *kwdict; | 
					
						
							|  |  |  |     Py_ssize_t i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(kwnames != NULL); | 
					
						
							|  |  |  |     nkwargs = PyTuple_GET_SIZE(kwnames); | 
					
						
							|  |  |  |     kwdict = _PyDict_NewPresized(nkwargs); | 
					
						
							|  |  |  |     if (kwdict == NULL) { | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (i = 0; i < nkwargs; i++) { | 
					
						
							|  |  |  |         PyObject *key = PyTuple_GET_ITEM(kwnames, i); | 
					
						
							|  |  |  |         PyObject *value = *values++; | 
					
						
							|  |  |  |         /* If key already exists, replace it with the new value */ | 
					
						
							|  |  |  |         if (PyDict_SetItem(kwdict, key, value)) { | 
					
						
							|  |  |  |             Py_DECREF(kwdict); | 
					
						
							|  |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return kwdict; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int | 
					
						
							| 
									
										
										
										
											2017-12-15 13:11:11 +02:00
										 |  |  | _PyStack_UnpackDict(PyObject *const *args, Py_ssize_t nargs, PyObject *kwargs, | 
					
						
							|  |  |  |                     PyObject *const **p_stack, PyObject **p_kwnames) | 
					
						
							| 
									
										
										
										
											2017-02-12 19:27:05 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     PyObject **stack, **kwstack; | 
					
						
							|  |  |  |     Py_ssize_t nkwargs; | 
					
						
							|  |  |  |     Py_ssize_t pos, i; | 
					
						
							|  |  |  |     PyObject *key, *value; | 
					
						
							|  |  |  |     PyObject *kwnames; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(nargs >= 0); | 
					
						
							|  |  |  |     assert(kwargs == NULL || PyDict_CheckExact(kwargs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (kwargs == NULL || (nkwargs = PyDict_GET_SIZE(kwargs)) == 0) { | 
					
						
							|  |  |  |         *p_stack = args; | 
					
						
							|  |  |  |         *p_kwnames = NULL; | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ((size_t)nargs > PY_SSIZE_T_MAX / sizeof(stack[0]) - (size_t)nkwargs) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     stack = PyMem_Malloc((nargs + nkwargs) * sizeof(stack[0])); | 
					
						
							|  |  |  |     if (stack == NULL) { | 
					
						
							|  |  |  |         PyErr_NoMemory(); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kwnames = PyTuple_New(nkwargs); | 
					
						
							|  |  |  |     if (kwnames == NULL) { | 
					
						
							|  |  |  |         PyMem_Free(stack); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Copy position arguments (borrowed references) */ | 
					
						
							|  |  |  |     memcpy(stack, args, nargs * sizeof(stack[0])); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kwstack = stack + nargs; | 
					
						
							|  |  |  |     pos = i = 0; | 
					
						
							|  |  |  |     /* This loop doesn't support lookup function mutating the dictionary
 | 
					
						
							|  |  |  |        to change its size. It's a deliberate choice for speed, this function is | 
					
						
							|  |  |  |        called in the performance critical hot code. */ | 
					
						
							|  |  |  |     while (PyDict_Next(kwargs, &pos, &key, &value)) { | 
					
						
							|  |  |  |         Py_INCREF(key); | 
					
						
							|  |  |  |         PyTuple_SET_ITEM(kwnames, i, key); | 
					
						
							|  |  |  |         /* The stack contains borrowed references */ | 
					
						
							|  |  |  |         kwstack[i] = value; | 
					
						
							|  |  |  |         i++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     *p_stack = stack; | 
					
						
							|  |  |  |     *p_kwnames = kwnames; | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } |