#include <stdio.h>#include <stdlib.h>/* co-routines in (gnu) c inspired by http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html instead of using an offet to a jump table, it's possible to use an offset to a code label in GNU C labels as values are defined here: http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html like sgtathams code, we store an offset to jump back into the function but we use a direct jmp instead of an internal jump table. *//* the preprocessor works in mysterious ways */#define __NAME__ __LABEL__(__LINE__)#define __LABEL__(x) __LABEL2__(x)#define __LABEL2__(x) __next##__##xtypedef unsigned int __offset__;#define CORO_STRUCT(x) typedef struct {__offset__ __state__; struct x;}#define CORO_MALLOC(t,cr) \ t *cr = malloc(sizeof(t));\ cr -> __state__ = 0#define CORO_STATIC(cr,t,in) \ static t (cr) = {0,in}; \ CORO_INIT(cr)#define CORO_INIT(cr) \ goto *(&&__init__ + (cr).__state__); \ __init__: /* use offsets instead of label addresses, to make code relocatable*/#define YIELD(cr, ...) { \ (cr).__state__ = &&__NAME__ - &&__init__; \ return __VA_ARGS__; \ } __NAME__:/* possible cleanup code */#define FAIL(cr) {}CORO_STRUCT({int i;}) foo_cr;/* example coroutine */int foo_static() { CORO_STATIC(cr,foo_cr, {10}); while (cr.i--) { YIELD(cr,cr.i); } return 0;}int foo_dynamic(foo_cr *cr) { CORO_INIT(*cr); cr->i = 9; while ((cr->i)--) { YIELD(*cr,cr->i); } return 0;}int main () { int a; while (1) { a = foo_static(); if (a <= 0) break; printf("-%d\n",a); } CORO_MALLOC(foo_cr,cr); while (1) { a = foo_dynamic(cr); if (a <= 0) break; printf("%d\n",a); } free(cr); return 0;}