J
Jerald Fijerald
Hello.
I'm trying to find an elegant way to longjmp to the callee
(aka "generators for C")
So far I've come to this experimental program (gcc only as it uses
__builtin_frame_address, although we can do without it):
======================================================================
/* longjmp to the callee */
#include <setjmp.h>
#include <stdio.h>
jmp_buf F;
jmp_buf F2;
static inline char* bfr ()
{
return __builtin_frame_address (0);
}
char *top;
int foo()
{
int i;
for (i = 0; i < 5; i++) {
printf (".i=%i\n", i);
if (i == 2) {
if (!setjmp (F2)) {
top = bfr();
//printf ("Mytop=%p\n", top);
longjmp (F, 1);
} else {
printf ("resumed...\n");
}
}
printf ("i=%i\n", i);
}
return 0;
}
int bar ()
{
return foo ();
}
int potatoe ()
{
int i, j;
for (i = 0, j = 10; i < j; i++)
printf ("%i ", i);
printf ("\n");
return 132;
}
int main ()
{
int i, j;
char *thistop;
for (i = 0; i < 3; i++)
if (!setjmp (F)) {
printf ("trying...\n");
bar();
} else {
/* preserve the stack */
j=40;
char CAP1[j];
thistop = bfr();
char GAP2 [top-thistop];
printf ("caught...\n");
/* test that stack is not polluted */
potatoe ();
/* longjmp to the callee and resume */
longjmp (F2, 2);
}
return 0;
}
=============================================================
Notes:
longjmp already supports jumping to a callee. The problem
is that we have to preserve the stack (and thus the function
potatoe() which is supposed to polute it).
The solution I found is to use C99 variable-length arrays to
displace the stacktop beyond the region we want to preserve.
I'm looking for ideas/enhancements to make this more portable,
safe, fast, etc. It must have been done before, right?
jf
I'm trying to find an elegant way to longjmp to the callee
(aka "generators for C")
So far I've come to this experimental program (gcc only as it uses
__builtin_frame_address, although we can do without it):
======================================================================
/* longjmp to the callee */
#include <setjmp.h>
#include <stdio.h>
jmp_buf F;
jmp_buf F2;
static inline char* bfr ()
{
return __builtin_frame_address (0);
}
char *top;
int foo()
{
int i;
for (i = 0; i < 5; i++) {
printf (".i=%i\n", i);
if (i == 2) {
if (!setjmp (F2)) {
top = bfr();
//printf ("Mytop=%p\n", top);
longjmp (F, 1);
} else {
printf ("resumed...\n");
}
}
printf ("i=%i\n", i);
}
return 0;
}
int bar ()
{
return foo ();
}
int potatoe ()
{
int i, j;
for (i = 0, j = 10; i < j; i++)
printf ("%i ", i);
printf ("\n");
return 132;
}
int main ()
{
int i, j;
char *thistop;
for (i = 0; i < 3; i++)
if (!setjmp (F)) {
printf ("trying...\n");
bar();
} else {
/* preserve the stack */
j=40;
char CAP1[j];
thistop = bfr();
char GAP2 [top-thistop];
printf ("caught...\n");
/* test that stack is not polluted */
potatoe ();
/* longjmp to the callee and resume */
longjmp (F2, 2);
}
return 0;
}
=============================================================
Notes:
longjmp already supports jumping to a callee. The problem
is that we have to preserve the stack (and thus the function
potatoe() which is supposed to polute it).
The solution I found is to use C99 variable-length arrays to
displace the stacktop beyond the region we want to preserve.
I'm looking for ideas/enhancements to make this more portable,
safe, fast, etc. It must have been done before, right?
jf