jpayne@69: #ifndef Py_CEVAL_H jpayne@69: #define Py_CEVAL_H jpayne@69: #ifdef __cplusplus jpayne@69: extern "C" { jpayne@69: #endif jpayne@69: jpayne@69: jpayne@69: /* Interface to random parts in ceval.c */ jpayne@69: jpayne@69: /* PyEval_CallObjectWithKeywords(), PyEval_CallObject(), PyEval_CallFunction jpayne@69: * and PyEval_CallMethod are kept for backward compatibility: PyObject_Call(), jpayne@69: * PyObject_CallFunction() and PyObject_CallMethod() are recommended to call jpayne@69: * a callable object. jpayne@69: */ jpayne@69: jpayne@69: PyAPI_FUNC(PyObject *) PyEval_CallObjectWithKeywords( jpayne@69: PyObject *callable, jpayne@69: PyObject *args, jpayne@69: PyObject *kwargs); jpayne@69: jpayne@69: /* Inline this */ jpayne@69: #define PyEval_CallObject(callable, arg) \ jpayne@69: PyEval_CallObjectWithKeywords(callable, arg, (PyObject *)NULL) jpayne@69: jpayne@69: PyAPI_FUNC(PyObject *) PyEval_CallFunction(PyObject *callable, jpayne@69: const char *format, ...); jpayne@69: PyAPI_FUNC(PyObject *) PyEval_CallMethod(PyObject *obj, jpayne@69: const char *name, jpayne@69: const char *format, ...); jpayne@69: jpayne@69: #ifndef Py_LIMITED_API jpayne@69: PyAPI_FUNC(void) PyEval_SetProfile(Py_tracefunc, PyObject *); jpayne@69: PyAPI_FUNC(void) PyEval_SetTrace(Py_tracefunc, PyObject *); jpayne@69: PyAPI_FUNC(void) _PyEval_SetCoroutineOriginTrackingDepth(int new_depth); jpayne@69: PyAPI_FUNC(int) _PyEval_GetCoroutineOriginTrackingDepth(void); jpayne@69: PyAPI_FUNC(void) _PyEval_SetAsyncGenFirstiter(PyObject *); jpayne@69: PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFirstiter(void); jpayne@69: PyAPI_FUNC(void) _PyEval_SetAsyncGenFinalizer(PyObject *); jpayne@69: PyAPI_FUNC(PyObject *) _PyEval_GetAsyncGenFinalizer(void); jpayne@69: #endif jpayne@69: jpayne@69: struct _frame; /* Avoid including frameobject.h */ jpayne@69: jpayne@69: PyAPI_FUNC(PyObject *) PyEval_GetBuiltins(void); jpayne@69: PyAPI_FUNC(PyObject *) PyEval_GetGlobals(void); jpayne@69: PyAPI_FUNC(PyObject *) PyEval_GetLocals(void); jpayne@69: PyAPI_FUNC(struct _frame *) PyEval_GetFrame(void); jpayne@69: jpayne@69: #ifndef Py_LIMITED_API jpayne@69: /* Helper to look up a builtin object */ jpayne@69: PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *); jpayne@69: /* Look at the current frame's (if any) code's co_flags, and turn on jpayne@69: the corresponding compiler flags in cf->cf_flags. Return 1 if any jpayne@69: flag was set, else return 0. */ jpayne@69: PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf); jpayne@69: #endif jpayne@69: jpayne@69: PyAPI_FUNC(int) Py_AddPendingCall(int (*func)(void *), void *arg); jpayne@69: PyAPI_FUNC(int) Py_MakePendingCalls(void); jpayne@69: jpayne@69: /* Protection against deeply nested recursive calls jpayne@69: jpayne@69: In Python 3.0, this protection has two levels: jpayne@69: * normal anti-recursion protection is triggered when the recursion level jpayne@69: exceeds the current recursion limit. It raises a RecursionError, and sets jpayne@69: the "overflowed" flag in the thread state structure. This flag jpayne@69: temporarily *disables* the normal protection; this allows cleanup code jpayne@69: to potentially outgrow the recursion limit while processing the jpayne@69: RecursionError. jpayne@69: * "last chance" anti-recursion protection is triggered when the recursion jpayne@69: level exceeds "current recursion limit + 50". By construction, this jpayne@69: protection can only be triggered when the "overflowed" flag is set. It jpayne@69: means the cleanup code has itself gone into an infinite loop, or the jpayne@69: RecursionError has been mistakingly ignored. When this protection is jpayne@69: triggered, the interpreter aborts with a Fatal Error. jpayne@69: jpayne@69: In addition, the "overflowed" flag is automatically reset when the jpayne@69: recursion level drops below "current recursion limit - 50". This heuristic jpayne@69: is meant to ensure that the normal anti-recursion protection doesn't get jpayne@69: disabled too long. jpayne@69: jpayne@69: Please note: this scheme has its own limitations. See: jpayne@69: http://mail.python.org/pipermail/python-dev/2008-August/082106.html jpayne@69: for some observations. jpayne@69: */ jpayne@69: PyAPI_FUNC(void) Py_SetRecursionLimit(int); jpayne@69: PyAPI_FUNC(int) Py_GetRecursionLimit(void); jpayne@69: jpayne@69: #define Py_EnterRecursiveCall(where) \ jpayne@69: (_Py_MakeRecCheck(PyThreadState_GET()->recursion_depth) && \ jpayne@69: _Py_CheckRecursiveCall(where)) jpayne@69: #define Py_LeaveRecursiveCall() \ jpayne@69: do{ if(_Py_MakeEndRecCheck(PyThreadState_GET()->recursion_depth)) \ jpayne@69: PyThreadState_GET()->overflowed = 0; \ jpayne@69: } while(0) jpayne@69: PyAPI_FUNC(int) _Py_CheckRecursiveCall(const char *where); jpayne@69: jpayne@69: /* Due to the macros in which it's used, _Py_CheckRecursionLimit is in jpayne@69: the stable ABI. It should be removed therefrom when possible. jpayne@69: */ jpayne@69: PyAPI_DATA(int) _Py_CheckRecursionLimit; jpayne@69: jpayne@69: #ifdef USE_STACKCHECK jpayne@69: /* With USE_STACKCHECK, trigger stack checks in _Py_CheckRecursiveCall() jpayne@69: on every 64th call to Py_EnterRecursiveCall. jpayne@69: */ jpayne@69: # define _Py_MakeRecCheck(x) \ jpayne@69: (++(x) > _Py_CheckRecursionLimit || \ jpayne@69: ++(PyThreadState_GET()->stackcheck_counter) > 64) jpayne@69: #else jpayne@69: # define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit) jpayne@69: #endif jpayne@69: jpayne@69: /* Compute the "lower-water mark" for a recursion limit. When jpayne@69: * Py_LeaveRecursiveCall() is called with a recursion depth below this mark, jpayne@69: * the overflowed flag is reset to 0. */ jpayne@69: #define _Py_RecursionLimitLowerWaterMark(limit) \ jpayne@69: (((limit) > 200) \ jpayne@69: ? ((limit) - 50) \ jpayne@69: : (3 * ((limit) >> 2))) jpayne@69: jpayne@69: #define _Py_MakeEndRecCheck(x) \ jpayne@69: (--(x) < _Py_RecursionLimitLowerWaterMark(_Py_CheckRecursionLimit)) jpayne@69: jpayne@69: #define Py_ALLOW_RECURSION \ jpayne@69: do { unsigned char _old = PyThreadState_GET()->recursion_critical;\ jpayne@69: PyThreadState_GET()->recursion_critical = 1; jpayne@69: jpayne@69: #define Py_END_ALLOW_RECURSION \ jpayne@69: PyThreadState_GET()->recursion_critical = _old; \ jpayne@69: } while(0); jpayne@69: jpayne@69: PyAPI_FUNC(const char *) PyEval_GetFuncName(PyObject *); jpayne@69: PyAPI_FUNC(const char *) PyEval_GetFuncDesc(PyObject *); jpayne@69: jpayne@69: PyAPI_FUNC(PyObject *) PyEval_EvalFrame(struct _frame *); jpayne@69: PyAPI_FUNC(PyObject *) PyEval_EvalFrameEx(struct _frame *f, int exc); jpayne@69: #ifndef Py_LIMITED_API jpayne@69: PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(struct _frame *f, int exc); jpayne@69: #endif jpayne@69: jpayne@69: /* Interface for threads. jpayne@69: jpayne@69: A module that plans to do a blocking system call (or something else jpayne@69: that lasts a long time and doesn't touch Python data) can allow other jpayne@69: threads to run as follows: jpayne@69: jpayne@69: ...preparations here... jpayne@69: Py_BEGIN_ALLOW_THREADS jpayne@69: ...blocking system call here... jpayne@69: Py_END_ALLOW_THREADS jpayne@69: ...interpret result here... jpayne@69: jpayne@69: The Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS pair expands to a jpayne@69: {}-surrounded block. jpayne@69: To leave the block in the middle (e.g., with return), you must insert jpayne@69: a line containing Py_BLOCK_THREADS before the return, e.g. jpayne@69: jpayne@69: if (...premature_exit...) { jpayne@69: Py_BLOCK_THREADS jpayne@69: PyErr_SetFromErrno(PyExc_OSError); jpayne@69: return NULL; jpayne@69: } jpayne@69: jpayne@69: An alternative is: jpayne@69: jpayne@69: Py_BLOCK_THREADS jpayne@69: if (...premature_exit...) { jpayne@69: PyErr_SetFromErrno(PyExc_OSError); jpayne@69: return NULL; jpayne@69: } jpayne@69: Py_UNBLOCK_THREADS jpayne@69: jpayne@69: For convenience, that the value of 'errno' is restored across jpayne@69: Py_END_ALLOW_THREADS and Py_BLOCK_THREADS. jpayne@69: jpayne@69: WARNING: NEVER NEST CALLS TO Py_BEGIN_ALLOW_THREADS AND jpayne@69: Py_END_ALLOW_THREADS!!! jpayne@69: jpayne@69: The function PyEval_InitThreads() should be called only from jpayne@69: init_thread() in "_threadmodule.c". jpayne@69: jpayne@69: Note that not yet all candidates have been converted to use this jpayne@69: mechanism! jpayne@69: */ jpayne@69: jpayne@69: PyAPI_FUNC(PyThreadState *) PyEval_SaveThread(void); jpayne@69: PyAPI_FUNC(void) PyEval_RestoreThread(PyThreadState *); jpayne@69: jpayne@69: PyAPI_FUNC(int) PyEval_ThreadsInitialized(void); jpayne@69: PyAPI_FUNC(void) PyEval_InitThreads(void); jpayne@69: Py_DEPRECATED(3.2) PyAPI_FUNC(void) PyEval_AcquireLock(void); jpayne@69: /* Py_DEPRECATED(3.2) */ PyAPI_FUNC(void) PyEval_ReleaseLock(void); jpayne@69: PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate); jpayne@69: PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate); jpayne@69: jpayne@69: #ifndef Py_LIMITED_API jpayne@69: PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds); jpayne@69: PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void); jpayne@69: #endif jpayne@69: jpayne@69: #ifndef Py_LIMITED_API jpayne@69: PyAPI_FUNC(Py_ssize_t) _PyEval_RequestCodeExtraIndex(freefunc); jpayne@69: #endif jpayne@69: jpayne@69: #define Py_BEGIN_ALLOW_THREADS { \ jpayne@69: PyThreadState *_save; \ jpayne@69: _save = PyEval_SaveThread(); jpayne@69: #define Py_BLOCK_THREADS PyEval_RestoreThread(_save); jpayne@69: #define Py_UNBLOCK_THREADS _save = PyEval_SaveThread(); jpayne@69: #define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \ jpayne@69: } jpayne@69: jpayne@69: #ifndef Py_LIMITED_API jpayne@69: PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *); jpayne@69: PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *); jpayne@69: #endif jpayne@69: jpayne@69: /* Masks and values used by FORMAT_VALUE opcode. */ jpayne@69: #define FVC_MASK 0x3 jpayne@69: #define FVC_NONE 0x0 jpayne@69: #define FVC_STR 0x1 jpayne@69: #define FVC_REPR 0x2 jpayne@69: #define FVC_ASCII 0x3 jpayne@69: #define FVS_MASK 0x4 jpayne@69: #define FVS_HAVE_SPEC 0x4 jpayne@69: jpayne@69: #ifdef __cplusplus jpayne@69: } jpayne@69: #endif jpayne@69: #endif /* !Py_CEVAL_H */