------------------------------------------------------------------------------
MC logo
Interface Structure
[^] CSc 6522
------------------------------------------------------------------------------
interface.c
#include <stdio.h>
#include <stdlib.h>

/**************************** Array-based stack ******************************/
struct arr_stack {
        int top;
        int contents[100];
};
int arr_init(stk) 
struct arr_stack *stk;

        stk->top = -1; 
}
int arr_push(stk,i) 
struct arr_stack *stk;
int i;

        stk->contents[++stk->top] = i;
}
int arr_pop(stk)
struct arr_stack *stk;

        return stk->contents[stk->top--];
}

/******************************* Linked stack *********************************/
struct stk_node {
        int cont;
        struct stk_node *next;
};
int lnk_init(stk)
struct stk_node **stk;

        *stk = NULL;
}
int lnk_push(stk, i)
struct stk_node **stk;
int i;

        struct stk_node *newnode = malloc(sizeof (struct stk_node));
        newnode->cont = i;
        newnode->next = *stk;
        *stk = newnode;
}
int lnk_pop(stk)
struct stk_node **stk;

        struct stk_node *zombie = *stk;
        int ret = zombie->cont;
        *stk = zombie->next;
        free(zombie);
        return ret;
}

/**************************** Interface Structures ***************************/
/* This is based on Fig. 3, where interface object points to the component. */
struct interface {
        char *intername;
        struct method *methods;
        void *object;
};

struct method {
        char *methname;
        int (*method)();
};

/* Find a named method in an interface. */
int error()
{
        fprintf(stderr, "Unknown method\n");
        abort();
}
typedef int (*meth_t)();
meth_t find(struct interface *inter, char *name)
{
        int i;

        for(i = 0; 1; ++i) {
                if(inter->methods[i].methname == NULL) return error;
                if(strcmp(inter->methods[i].methname, name) == 0)
                        return inter->methods[i].method;
        }
}

/*************************** Interface Creators *******************************/
/* Array stack. */
struct interface *mk_arr_stck_iface(struct arr_stack *stk)
{
        struct interface *iface = malloc(sizeof (struct interface));
        iface->intername = "stack";
        iface->object = stk;
        iface->methods = malloc(4*sizeof(struct method));
        iface->methods[0].methname = "init";
        iface->methods[0].method = arr_init;
        iface->methods[1].methname = "push";
        iface->methods[1].method = arr_push;
        iface->methods[2].methname = "pop";
        iface->methods[2].method = arr_pop;
        iface->methods[3].methname = NULL;
        iface->methods[3].method = NULL;

        return iface;
}

/* Linked stack. */
struct interface *mk_lnk_stck_iface(struct stk_node **stk)
{
        struct interface *iface = malloc(sizeof (struct interface));
        iface->intername = "stack";
        iface->object = stk;
        iface->methods = malloc(4*sizeof(struct method));
        iface->methods[0].methname = "init";
        iface->methods[0].method = lnk_init;
        iface->methods[1].methname = "push";
        iface->methods[1].method = lnk_push;
        iface->methods[2].methname = "pop";
        iface->methods[2].method = lnk_pop;
        iface->methods[3].methname = NULL;
        iface->methods[3].method = NULL;

        return iface;
}

/* Doace some stuff with an interface. */
void runstack(struct interface *i)
{
        int j;

        /* Initialize. */
        find(i, "init")(i->object);
        
        /* Push stuff. */
        for(j = 0; j < 4; j++)
                find(i, "push")(i->object, 2*j + 3);

        /* Pop and print. */
        for(j = 0; j < 4; j++)
                printf("%d ", find(i, "pop")(i->object));
        putchar('\n');
}

main()
{
        /* The two objects, or "components" */
        struct arr_stack arr_stack;
        struct stk_node *lnk_stack;

        /* Create interfaces for each. */
        struct interface *arr_inter = mk_arr_stck_iface(&arr_stack);
        struct interface *lnk_inter = mk_lnk_stck_iface(&lnk_stack);

        /* Run something with each. */
        runstack(arr_inter);
        runstack(lnk_inter);
}