#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ucontext.h>

enum { STATE_ONE, STATE_TWO, STATE_DONE };

struct execution_state {
    int state_;
    ucontext_t main_ctx_;
    ucontext_t alt_ctx_;
    char alt_stack_[32*1024];
} es;

void deferred_print (const char *fmt, ...) {
    va_list ap;
    while (es.state_ == STATE_ONE) {
        es.state_ = STATE_TWO;
        swapcontext(&es.main_ctx_, &es.alt_ctx_);
    }
    va_start(ap, fmt);
    vprintf(fmt, ap);
    va_end(ap);
}

void state_one () {
    puts(__func__);
    deferred_print("this is a deferred print from %s\n", __func__);
    es.state_ = STATE_DONE;
}

void state_two () {
    puts(__func__);
    if (rand() > RAND_MAX/4) es.state_ = STATE_ONE;
    setcontext(&es.main_ctx_);
}

void state_machine () {
    while (es.state_ != STATE_DONE) {
        (void (*[])()){ state_one, state_two }[es.state_]();
    }
}

void es_init () {
    es.state_ = STATE_ONE;
    getcontext(&es.alt_ctx_);
    es.alt_ctx_.uc_stack.ss_sp = es.alt_stack_;
    es.alt_ctx_.uc_stack.ss_size = sizeof(es.alt_stack_);
    es.alt_ctx_.uc_link = &es.main_ctx_;
    makecontext(&es.alt_ctx_, state_machine, 0);
    srand((unsigned)time(0));
}

int main () {
    es_init();
    puts("start");
    state_machine();
    puts("finish");
    return 0;
}
