------------------------------------------------------------------------------
MC logo
Save The Registers!
[^] CSc 422 Lecture Slides
------------------------------------------------------------------------------
pingpong.c
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

/* State used in two functions. */
jmp_buf func_state, main_state;

/* Random message. */
const char *msg;

void func()
{
        /* Meaningless counter. */
        int m;

        /* setjmp() return value. */
        int ret;

        /* This copies the registers to func_state, and returns 0.  When
           the register values are restored by longjmp, the PC is changed
           so this function returns again.  It's return value is specified
           in the longjmp call. */
        ret = setjmp(func_state);
        if(ret == 0) {
                /* First time setjmp() returns. */
                printf("Begin func()\n");
                m = 1;
                longjmp(main_state, 1);
        }

        /* We reach here when setjmp() returns as a result of a register
           restore by longjmp().  Do a bit, depending on the return value
           sent by the restore, then restore the registers in main_state
           which will return control there. */
        printf("func: ret = %d, m = %d, msg = %s\n", ret, m, msg);
        if(ret == 1) m *= 2;
        longjmp(main_state, 1);

        /* Control never reaches this point. */
        printf("func done\n");
}

main()
{
        /* Iteration counter */
        int n = 0;

        /* A set of messages to store in rotation. */
        const char *msgs[] = { "Moonbat", "Ringworm", "Northstar",
                               "Swamp", "Polarbear", "Snakeoil" };

        /* Save our registers in main_state, then, on the original
           save, call the function. */
        if(!setjmp(main_state)) func();

        /* On restores from the function, set a message and go back there.
           Do this 10 times, then stop. */
        msg = msgs[n%6];
        if(n++ < 10) longjmp(func_state, n%2 + 1);

        printf("Done\n");

        exit(0);
}

/* Remember this:
      setjmp()  can return any number of times.
      longjmp() the longjmp call does not return; instead, it makes 
                last setjmp() on the same buffer return again.
*/

Output:
Begin func()
func: ret = 2, m = 1, msg = Moonbat
func: ret = 1, m = 1, msg = Ringworm
func: ret = 2, m = 2, msg = Northstar
func: ret = 1, m = 2, msg = Swamp
func: ret = 2, m = 4, msg = Polarbear
func: ret = 1, m = 4, msg = Snakeoil
func: ret = 2, m = 8, msg = Moonbat
func: ret = 1, m = 8, msg = Ringworm
func: ret = 2, m = 16, msg = Northstar
func: ret = 1, m = 16, msg = Swamp
Done