annotate DEPENDENCIES/mingw32/Python27/include/pyfpe.h @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2a2c65a20a8b
children
rev   line source
Chris@87 1 #ifndef Py_PYFPE_H
Chris@87 2 #define Py_PYFPE_H
Chris@87 3 #ifdef __cplusplus
Chris@87 4 extern "C" {
Chris@87 5 #endif
Chris@87 6 /*
Chris@87 7 ---------------------------------------------------------------------
Chris@87 8 / Copyright (c) 1996. \
Chris@87 9 | The Regents of the University of California. |
Chris@87 10 | All rights reserved. |
Chris@87 11 | |
Chris@87 12 | Permission to use, copy, modify, and distribute this software for |
Chris@87 13 | any purpose without fee is hereby granted, provided that this en- |
Chris@87 14 | tire notice is included in all copies of any software which is or |
Chris@87 15 | includes a copy or modification of this software and in all |
Chris@87 16 | copies of the supporting documentation for such software. |
Chris@87 17 | |
Chris@87 18 | This work was produced at the University of California, Lawrence |
Chris@87 19 | Livermore National Laboratory under contract no. W-7405-ENG-48 |
Chris@87 20 | between the U.S. Department of Energy and The Regents of the |
Chris@87 21 | University of California for the operation of UC LLNL. |
Chris@87 22 | |
Chris@87 23 | DISCLAIMER |
Chris@87 24 | |
Chris@87 25 | This software was prepared as an account of work sponsored by an |
Chris@87 26 | agency of the United States Government. Neither the United States |
Chris@87 27 | Government nor the University of California nor any of their em- |
Chris@87 28 | ployees, makes any warranty, express or implied, or assumes any |
Chris@87 29 | liability or responsibility for the accuracy, completeness, or |
Chris@87 30 | usefulness of any information, apparatus, product, or process |
Chris@87 31 | disclosed, or represents that its use would not infringe |
Chris@87 32 | privately-owned rights. Reference herein to any specific commer- |
Chris@87 33 | cial products, process, or service by trade name, trademark, |
Chris@87 34 | manufacturer, or otherwise, does not necessarily constitute or |
Chris@87 35 | imply its endorsement, recommendation, or favoring by the United |
Chris@87 36 | States Government or the University of California. The views and |
Chris@87 37 | opinions of authors expressed herein do not necessarily state or |
Chris@87 38 | reflect those of the United States Government or the University |
Chris@87 39 | of California, and shall not be used for advertising or product |
Chris@87 40 \ endorsement purposes. /
Chris@87 41 ---------------------------------------------------------------------
Chris@87 42 */
Chris@87 43
Chris@87 44 /*
Chris@87 45 * Define macros for handling SIGFPE.
Chris@87 46 * Lee Busby, LLNL, November, 1996
Chris@87 47 * busby1@llnl.gov
Chris@87 48 *
Chris@87 49 *********************************************
Chris@87 50 * Overview of the system for handling SIGFPE:
Chris@87 51 *
Chris@87 52 * This file (Include/pyfpe.h) defines a couple of "wrapper" macros for
Chris@87 53 * insertion into your Python C code of choice. Their proper use is
Chris@87 54 * discussed below. The file Python/pyfpe.c defines a pair of global
Chris@87 55 * variables PyFPE_jbuf and PyFPE_counter which are used by the signal
Chris@87 56 * handler for SIGFPE to decide if a particular exception was protected
Chris@87 57 * by the macros. The signal handler itself, and code for enabling the
Chris@87 58 * generation of SIGFPE in the first place, is in a (new) Python module
Chris@87 59 * named fpectl. This module is standard in every respect. It can be loaded
Chris@87 60 * either statically or dynamically as you choose, and like any other
Chris@87 61 * Python module, has no effect until you import it.
Chris@87 62 *
Chris@87 63 * In the general case, there are three steps toward handling SIGFPE in any
Chris@87 64 * Python code:
Chris@87 65 *
Chris@87 66 * 1) Add the *_PROTECT macros to your C code as required to protect
Chris@87 67 * dangerous floating point sections.
Chris@87 68 *
Chris@87 69 * 2) Turn on the inclusion of the code by adding the ``--with-fpectl''
Chris@87 70 * flag at the time you run configure. If the fpectl or other modules
Chris@87 71 * which use the *_PROTECT macros are to be dynamically loaded, be
Chris@87 72 * sure they are compiled with WANT_SIGFPE_HANDLER defined.
Chris@87 73 *
Chris@87 74 * 3) When python is built and running, import fpectl, and execute
Chris@87 75 * fpectl.turnon_sigfpe(). This sets up the signal handler and enables
Chris@87 76 * generation of SIGFPE whenever an exception occurs. From this point
Chris@87 77 * on, any properly trapped SIGFPE should result in the Python
Chris@87 78 * FloatingPointError exception.
Chris@87 79 *
Chris@87 80 * Step 1 has been done already for the Python kernel code, and should be
Chris@87 81 * done soon for the NumPy array package. Step 2 is usually done once at
Chris@87 82 * python install time. Python's behavior with respect to SIGFPE is not
Chris@87 83 * changed unless you also do step 3. Thus you can control this new
Chris@87 84 * facility at compile time, or run time, or both.
Chris@87 85 *
Chris@87 86 ********************************
Chris@87 87 * Using the macros in your code:
Chris@87 88 *
Chris@87 89 * static PyObject *foobar(PyObject *self,PyObject *args)
Chris@87 90 * {
Chris@87 91 * ....
Chris@87 92 * PyFPE_START_PROTECT("Error in foobar", return 0)
Chris@87 93 * result = dangerous_op(somearg1, somearg2, ...);
Chris@87 94 * PyFPE_END_PROTECT(result)
Chris@87 95 * ....
Chris@87 96 * }
Chris@87 97 *
Chris@87 98 * If a floating point error occurs in dangerous_op, foobar returns 0 (NULL),
Chris@87 99 * after setting the associated value of the FloatingPointError exception to
Chris@87 100 * "Error in foobar". ``Dangerous_op'' can be a single operation, or a block
Chris@87 101 * of code, function calls, or any combination, so long as no alternate
Chris@87 102 * return is possible before the PyFPE_END_PROTECT macro is reached.
Chris@87 103 *
Chris@87 104 * The macros can only be used in a function context where an error return
Chris@87 105 * can be recognized as signaling a Python exception. (Generally, most
Chris@87 106 * functions that return a PyObject * will qualify.)
Chris@87 107 *
Chris@87 108 * Guido's original design suggestion for PyFPE_START_PROTECT and
Chris@87 109 * PyFPE_END_PROTECT had them open and close a local block, with a locally
Chris@87 110 * defined jmp_buf and jmp_buf pointer. This would allow recursive nesting
Chris@87 111 * of the macros. The Ansi C standard makes it clear that such local
Chris@87 112 * variables need to be declared with the "volatile" type qualifier to keep
Chris@87 113 * setjmp from corrupting their values. Some current implementations seem
Chris@87 114 * to be more restrictive. For example, the HPUX man page for setjmp says
Chris@87 115 *
Chris@87 116 * Upon the return from a setjmp() call caused by a longjmp(), the
Chris@87 117 * values of any non-static local variables belonging to the routine
Chris@87 118 * from which setjmp() was called are undefined. Code which depends on
Chris@87 119 * such values is not guaranteed to be portable.
Chris@87 120 *
Chris@87 121 * I therefore decided on a more limited form of nesting, using a counter
Chris@87 122 * variable (PyFPE_counter) to keep track of any recursion. If an exception
Chris@87 123 * occurs in an ``inner'' pair of macros, the return will apparently
Chris@87 124 * come from the outermost level.
Chris@87 125 *
Chris@87 126 */
Chris@87 127
Chris@87 128 #ifdef WANT_SIGFPE_HANDLER
Chris@87 129 #include <signal.h>
Chris@87 130 #include <setjmp.h>
Chris@87 131 #include <math.h>
Chris@87 132 extern jmp_buf PyFPE_jbuf;
Chris@87 133 extern int PyFPE_counter;
Chris@87 134 extern double PyFPE_dummy(void *);
Chris@87 135
Chris@87 136 #define PyFPE_START_PROTECT(err_string, leave_stmt) \
Chris@87 137 if (!PyFPE_counter++ && setjmp(PyFPE_jbuf)) { \
Chris@87 138 PyErr_SetString(PyExc_FloatingPointError, err_string); \
Chris@87 139 PyFPE_counter = 0; \
Chris@87 140 leave_stmt; \
Chris@87 141 }
Chris@87 142
Chris@87 143 /*
Chris@87 144 * This (following) is a heck of a way to decrement a counter. However,
Chris@87 145 * unless the macro argument is provided, code optimizers will sometimes move
Chris@87 146 * this statement so that it gets executed *before* the unsafe expression
Chris@87 147 * which we're trying to protect. That pretty well messes things up,
Chris@87 148 * of course.
Chris@87 149 *
Chris@87 150 * If the expression(s) you're trying to protect don't happen to return a
Chris@87 151 * value, you will need to manufacture a dummy result just to preserve the
Chris@87 152 * correct ordering of statements. Note that the macro passes the address
Chris@87 153 * of its argument (so you need to give it something which is addressable).
Chris@87 154 * If your expression returns multiple results, pass the last such result
Chris@87 155 * to PyFPE_END_PROTECT.
Chris@87 156 *
Chris@87 157 * Note that PyFPE_dummy returns a double, which is cast to int.
Chris@87 158 * This seeming insanity is to tickle the Floating Point Unit (FPU).
Chris@87 159 * If an exception has occurred in a preceding floating point operation,
Chris@87 160 * some architectures (notably Intel 80x86) will not deliver the interrupt
Chris@87 161 * until the *next* floating point operation. This is painful if you've
Chris@87 162 * already decremented PyFPE_counter.
Chris@87 163 */
Chris@87 164 #define PyFPE_END_PROTECT(v) PyFPE_counter -= (int)PyFPE_dummy(&(v));
Chris@87 165
Chris@87 166 #else
Chris@87 167
Chris@87 168 #define PyFPE_START_PROTECT(err_string, leave_stmt)
Chris@87 169 #define PyFPE_END_PROTECT(v)
Chris@87 170
Chris@87 171 #endif
Chris@87 172
Chris@87 173 #ifdef __cplusplus
Chris@87 174 }
Chris@87 175 #endif
Chris@87 176 #endif /* !Py_PYFPE_H */