    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>

    typedef int abstract_func_type ();

    typedef struct htentry {
        struct htentry *next;
        abstract_func_type *k;
        abstract_func_type **fpp;
    } htentry;
    static htentry *hashtable[101];

    static void insert (abstract_func_type *k, abstract_func_type **p) {
        htentry *e = malloc(sizeof(htentry));
        int i = ((char *)k - (char *)0) % 101;
        e->k = k;
        e->fpp = p;
        e->next = hashtable[i];
        hashtable[i] = e;
    }

    static abstract_func_type ** lookup (abstract_func_type *k) {
        int i = ((char *)k - (char *)0) % 101;
        htentry *e = hashtable[i];
        while (e) {
            if (e->k == k) return e->fpp;
            e = e->next;
        }
        return 0;
    }

    abstract_func_type * abstract_func_get (abstract_func_type *k) {
        abstract_func_type **f = lookup(k);
        if (f) return *f;
        return 0;
    }

    int abstract_func_set (abstract_func_type *k, abstract_func_type *p) {
        abstract_func_type **f = lookup(k);
        if (f) {
            *f = p;
            return 0;
        }
        return -ENOENT;
    }

    #define DEFINE_ABSTRACT_FUNC(func) \
        static int static_##func (); \
        static abstract_func_type *func##_ptr = static_##func; \
        int func () { return func##_ptr(); } \
        static int static_##func ()

    DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); }
    DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); }

    void abstract_func_init () {
        insert(foo, &foo_ptr);
        insert(bar, &bar_ptr);
    }

    void swap(abstract_func_type *a, abstract_func_type *b) {
        abstract_func_type *ap = abstract_func_get(a);
        abstract_func_type *bp = abstract_func_get(b);
        abstract_func_set(a, bp);
        abstract_func_set(b, ap);
    }

    int
    main ()
    {
        abstract_func_init();
        puts("before swap");
        foo();
        bar();
        swap(foo, bar);
        puts("after swap");
        foo();
        bar();
        return 0;
    }
