Oh, this was a mess. The old code would convert an exception from a
Python handler into `PGEN_ABORT', and hope that the exception state was
still available when the overall operation ended.
This doesn't work. In particular, steppers and testers are finalized by
calling them with `PGEN_DONE', and the interpreter doesn't like
re-entering Python with an exception set. (In debug builds, this is an
assertion failure.)
Overhaul all of this nonsense.
* Add a collection of utilities for saving and restoring the exception
state.
* Add a hook, in the `catacomb' module, for reporting `lost'
exceptions, for the case where further exceptions are raised while
responding to a first exception.
* Use a larger `pypgev' structure to track the state of a Python event
handler through the framework. This structure holds a reference to
the Python object itself, and a slot for recording an exception.
* When a Python handler fails, stash the exception state in the slot
provided by the `pypgev' structure if there isn't one already, and
clear the pending exception. If there is already an exception in
the slot, then report the new exception through the hook described
above.
* Once a `pgen' operation completes, if it raised any exceptions at
all, then the first of these is left in the exception slot. If it
fails otherwise, then we supply a generic exception.