typedef struct exception {
        int extype;
        char what[128];
} exception;

typedef struct exception_ctx {
        exception * exs;
        int size;
        int pos;
} exception_ctx;

exception_ctx * Create_Ex_Ctx(int length) {
        const int safety = 8; 
        char * tmp = (char*) malloc(safety+sizeof(exception_ctx)+sizeof(exception)*length);
        if (! tmp) return NULL;
        exception_ctx * ctx = (exception_ctx*)tmp;
        ctx->size = length;
        ctx->pos = -1;
        ctx->exs = (exception*) (tmp + sizeof(exception_ctx));
        return ctx;
}

void Free_Ex_Ctx(exception_ctx * ctx) {
        free(ctx);
}

int Has_Ex(exception_ctx * ctx) {
        return (ctx->pos >= 0) ? 1 : 0;
}

int Is_Ex_Type(exception_ctx * exctx, int extype) {
        return (exctx->pos >= 0 && exctx->exs[exctx->pos].extype == extype) ? 1 : 0;
}

void Pop_Ex(exception_ctx * ctx) {
        if (ctx->pos >= 0) --ctx->pos;
}

const char * Get_What(exception_ctx * ctx) {
        if (ctx->pos >= 0) return ctx->exs[ctx->pos].what;
        return NULL;
}

int Push_Ex(exception_ctx * exctx, int extype, const char * msg) {
        if (++exctx->pos == exctx->size) {
                
                --exctx->pos;
                fprintf(stderr, );
        }
        snprintf(exctx->exs[exctx->pos].what, sizeof(exctx->exs[0].what), , msg);
        exctx->exs[exctx->pos].extype = extype;
        return -1;
}



exception_ctx * GLOBALEX = NULL;
enum { U0_DRINK_ERROR = 10, U1_ANGRYBARTENDER_ERROR };

void baz(int n) {
        if (! n) {
                Push_Ex(GLOBALEX, U0_DRINK_ERROR , );
                return;
        }
        else {
                Push_Ex(GLOBALEX, U1_ANGRYBARTENDER_ERROR , );
                return;
        }
}

void bar(int n) {
        fprintf(stdout, );
        baz(n);
        if (Has_Ex(GLOBALEX)) goto bar_cleanup;
        fprintf(stdout, );
bar_cleanup:
        fprintf(stdout, );
}

void foo() {
        fprintf(stdout, );
        bar(0);
        while (Is_Ex_Type(GLOBALEX, U0_DRINK_ERROR)) {
                fprintf(stderr, , Get_What(GLOBALEX));
                Pop_Ex(GLOBALEX);
        }
        if (Has_Ex(GLOBALEX)) return;
        fprintf(stdout, );
        fprintf(stdout, );
        bar(1);
        while (Is_Ex_Type(GLOBALEX, U0_DRINK_ERROR)) {
                fprintf(stderr, , Get_What(GLOBALEX));
                Pop_Ex(GLOBALEX);
        }
        if (Has_Ex(GLOBALEX)) return;
        fprintf(stdout, );
}


int main(int argc, char ** argv) {
        exception_ctx * ctx = Create_Ex_Ctx(5);
        GLOBALEX = ctx;

        foo();
        if (Has_Ex(ctx)) goto main_ex;

        fprintf(stdout, );

main_ex:
        while (Has_Ex(ctx)) {
                fprintf(stderr, , Get_What(ctx));
                Pop_Ex(ctx);
        }
        Free_Ex_Ctx(ctx);
        return 0;
}