import inspect
import types
import ctypes
import sys
import traceback
frameobject_fields = [
# PyObject_VAR_HEAD
( "ob_refcnt" , ctypes.c_int64 ) ,
( "ob_type" , ctypes.py_object ) ,
( "ob_size" , ctypes.c_ssize_t ) ,
# struct _frame *f_back; /* previous frame, or NULL */
( "f_back" , ctypes.c_void_p ) ,
# PyCodeObject *f_code; /* code segment */
( "f_code" , ctypes.c_void_p ) ,
# PyObject *f_builtins; /* builtin symbol table (PyDictObject) */
( "f_builtins" , ctypes.py_object ) ,
# PyObject *f_globals; /* global symbol table (PyDictObject) */
( "f_globals" , ctypes.py_object ) ,
####
( "f_locals" , ctypes.py_object ) ,
( "f_valuestack" , ctypes.POINTER ( ctypes.py_object ) ) ,
( "f_stacktop" , ctypes.POINTER ( ctypes.py_object ) ) ,
( "f_trace" , ctypes.py_object ) ,
( "f_exc_type" , ctypes.py_object ) ,
( "f_exc_value" , ctypes.py_object ) ,
( "f_exc_traceback" , ctypes.py_object ) ,
( "f_tstate" , ctypes.c_void_p ) ,
( "f_lasti" , ctypes.c_int ) ,
]
if hasattr ( sys , "getobjects" ) :
# This python was compiled with debugging enabled.
frameobject_fields = [
( "_ob_next" , ctypes.c_void_p ) ,
( "_ob_prev" , ctypes.c_void_p ) ,
] + frameobject_fields
class PyFrameObject( ctypes.Structure ) :
_fields_ = frameobject_fields
class Continuation:
def __init__ ( self , frame) :
self .frame = frame
self .lasti = frame.f_lasti
self .lastis = [ ]
frame = frame.f_back
while frame is not None :
self .lastis .append ( frame.f_lasti )
frame = frame.f_back
def __call__ ( self ) :
print ( '\n before' )
traceback .print_stack ( )
cur_frame = PyFrameObject.from_address ( id ( inspect .currentframe ( ) ) )
PyFrameObject.from_address ( cur_frame.f_back ) .ob_refcnt -= 1
cur_frame.f_back = id ( self .frame )
PyFrameObject.from_address ( id ( self .frame ) ) .ob_refcnt += 1
frame = self .frame
_frame = PyFrameObject.from_address ( id ( frame) )
_frame.f_lasti = self .lasti + 4
frame = frame.f_back
for lasti in self .lastis :
if len ( frame.f_code .co_code ) != frame.f_lasti + 2 :
break
_frame = PyFrameObject.from_address ( id ( frame) )
_frame.f_lasti = lasti + 4
frame = frame.f_back
print ( '\n after' )
traceback .print_stack ( )
def callcc( f) :
f( Continuation( inspect .currentframe ( ) .f_back ) )
cc = None
def func( ) :
bar = 0
print ( "This should show only once" )
def save_cont( k) :
global cc
cc = k
callcc( save_cont)
print ( bar)
bar += 1
def g( ) :
func( )
print ( "This should show multiple times" )
sys .stderr = sys .stdout
g( )
cc( )
aW1wb3J0IGluc3BlY3QKaW1wb3J0IHR5cGVzCmltcG9ydCBjdHlwZXMKaW1wb3J0IHN5cwppbXBvcnQgdHJhY2ViYWNrCgoKZnJhbWVvYmplY3RfZmllbGRzID0gWwoJIyBQeU9iamVjdF9WQVJfSEVBRAoJKCJvYl9yZWZjbnQiLCBjdHlwZXMuY19pbnQ2NCksCgkoIm9iX3R5cGUiLCBjdHlwZXMucHlfb2JqZWN0KSwKCSgib2Jfc2l6ZSIsIGN0eXBlcy5jX3NzaXplX3QpLAoJIyBzdHJ1Y3QgX2ZyYW1lICpmX2JhY2s7ICAgICAgLyogcHJldmlvdXMgZnJhbWUsIG9yIE5VTEwgKi8KCSgiZl9iYWNrIiwgY3R5cGVzLmNfdm9pZF9wKSwKCSMgUHlDb2RlT2JqZWN0ICpmX2NvZGU7ICAgICAgIC8qIGNvZGUgc2VnbWVudCAqLwoJKCJmX2NvZGUiLCBjdHlwZXMuY192b2lkX3ApLAoJIyBQeU9iamVjdCAqZl9idWlsdGluczsgICAgICAgLyogYnVpbHRpbiBzeW1ib2wgdGFibGUgKFB5RGljdE9iamVjdCkgKi8KCSgiZl9idWlsdGlucyIsIGN0eXBlcy5weV9vYmplY3QpLAoJIyBQeU9iamVjdCAqZl9nbG9iYWxzOyAgICAgICAgLyogZ2xvYmFsIHN5bWJvbCB0YWJsZSAoUHlEaWN0T2JqZWN0KSAqLwoJKCJmX2dsb2JhbHMiLCBjdHlwZXMucHlfb2JqZWN0KSwKCSMjIyMKCSgiZl9sb2NhbHMiLCBjdHlwZXMucHlfb2JqZWN0KSwKCSgiZl92YWx1ZXN0YWNrIiwgY3R5cGVzLlBPSU5URVIoY3R5cGVzLnB5X29iamVjdCkpLAoJKCJmX3N0YWNrdG9wIiwgY3R5cGVzLlBPSU5URVIoY3R5cGVzLnB5X29iamVjdCkpLAoJKCJmX3RyYWNlIiwgY3R5cGVzLnB5X29iamVjdCksCgkoImZfZXhjX3R5cGUiLCBjdHlwZXMucHlfb2JqZWN0KSwKCSgiZl9leGNfdmFsdWUiLCBjdHlwZXMucHlfb2JqZWN0KSwKCSgiZl9leGNfdHJhY2ViYWNrIiwgY3R5cGVzLnB5X29iamVjdCksCgkoImZfdHN0YXRlIiwgY3R5cGVzLmNfdm9pZF9wKSwKCSgiZl9sYXN0aSIsIGN0eXBlcy5jX2ludCksCl0KaWYgaGFzYXR0cihzeXMsICJnZXRvYmplY3RzIik6CgkjIFRoaXMgcHl0aG9uIHdhcyBjb21waWxlZCB3aXRoIGRlYnVnZ2luZyBlbmFibGVkLgoJZnJhbWVvYmplY3RfZmllbGRzID0gWwoJCSgiX29iX25leHQiLCBjdHlwZXMuY192b2lkX3ApLAoJCSgiX29iX3ByZXYiLCBjdHlwZXMuY192b2lkX3ApLAoJXSArIGZyYW1lb2JqZWN0X2ZpZWxkcwpjbGFzcyBQeUZyYW1lT2JqZWN0KGN0eXBlcy5TdHJ1Y3R1cmUpOgoJX2ZpZWxkc18gPSBmcmFtZW9iamVjdF9maWVsZHMKCgpjbGFzcyBDb250aW51YXRpb246CglkZWYgX19pbml0X18oc2VsZiwgZnJhbWUpOgoJCXNlbGYuZnJhbWUgPSBmcmFtZQoJCXNlbGYubGFzdGkgPSBmcmFtZS5mX2xhc3RpCgkJc2VsZi5sYXN0aXMgPSBbXQoKCQlmcmFtZSA9IGZyYW1lLmZfYmFjawoJCXdoaWxlIGZyYW1lIGlzIG5vdCBOb25lOgoJCQlzZWxmLmxhc3Rpcy5hcHBlbmQoZnJhbWUuZl9sYXN0aSkKCQkJZnJhbWUgPSBmcmFtZS5mX2JhY2sKCglkZWYgX19jYWxsX18oc2VsZik6CgkJcHJpbnQoJ1xuYmVmb3JlJykKCQl0cmFjZWJhY2sucHJpbnRfc3RhY2soKQoKCQljdXJfZnJhbWUgPSBQeUZyYW1lT2JqZWN0LmZyb21fYWRkcmVzcyhpZChpbnNwZWN0LmN1cnJlbnRmcmFtZSgpKSkKCQlQeUZyYW1lT2JqZWN0LmZyb21fYWRkcmVzcyhjdXJfZnJhbWUuZl9iYWNrKS5vYl9yZWZjbnQgLT0gMQoJCWN1cl9mcmFtZS5mX2JhY2sgPSBpZChzZWxmLmZyYW1lKQoJCVB5RnJhbWVPYmplY3QuZnJvbV9hZGRyZXNzKGlkKHNlbGYuZnJhbWUpKS5vYl9yZWZjbnQgKz0gMQoKCQlmcmFtZSA9IHNlbGYuZnJhbWUKCQlfZnJhbWUgPSBQeUZyYW1lT2JqZWN0LmZyb21fYWRkcmVzcyhpZChmcmFtZSkpCgkJX2ZyYW1lLmZfbGFzdGkgPSBzZWxmLmxhc3RpICsgNAoKCQlmcmFtZSA9IGZyYW1lLmZfYmFjawoJCWZvciBsYXN0aSBpbiBzZWxmLmxhc3RpczoKCQkJaWYgbGVuKGZyYW1lLmZfY29kZS5jb19jb2RlKSAhPSBmcmFtZS5mX2xhc3RpICsgMjoKCQkJCWJyZWFrCgkJCV9mcmFtZSA9IFB5RnJhbWVPYmplY3QuZnJvbV9hZGRyZXNzKGlkKGZyYW1lKSkKCQkJX2ZyYW1lLmZfbGFzdGkgPSBsYXN0aSArIDQKCQkJZnJhbWUgPSBmcmFtZS5mX2JhY2sKCgkJcHJpbnQoJ1xuYWZ0ZXInKQoJCXRyYWNlYmFjay5wcmludF9zdGFjaygpCgoKZGVmIGNhbGxjYyhmKToKCWYoQ29udGludWF0aW9uKGluc3BlY3QuY3VycmVudGZyYW1lKCkuZl9iYWNrKSkKCgpjYyA9IE5vbmUKCgpkZWYgZnVuYygpOgoJYmFyID0gMAoJcHJpbnQoIlRoaXMgc2hvdWxkIHNob3cgb25seSBvbmNlIikKCWRlZiBzYXZlX2NvbnQoayk6CgkJZ2xvYmFsIGNjCgkJY2MgPSBrCgljYWxsY2Moc2F2ZV9jb250KQoJcHJpbnQoYmFyKQoJYmFyICs9IDEKCgpkZWYgZygpOgoJZnVuYygpCglwcmludCgiVGhpcyBzaG91bGQgc2hvdyBtdWx0aXBsZSB0aW1lcyIpCgpzeXMuc3RkZXJyID0gc3lzLnN0ZG91dApnKCkKY2MoKQ==