#include "common.h"
#include "generic-stack.h"

#define MAX_OPS 2

static void print_int(void *d) {
    printf("%10d\n", *((int *) d));
    return;
}

static void print_double(void *d) {
    printf("%10.4lf\n", *((double *) d));
    return;
}

static void print_string(void *d) {
    printf("%s\n", *((char **) d));
    return;
}


int main(int ac, char *av[])
{
    int i, n = -1234;
    double f = -1234.4321;
    char *str;
    STACK s;

    if (ac < 2)
        ERR_MESG("Usage: gstack-main <type> [element1 element2 ... ]");
    switch(av[1][0]) {
    case 'i': /* integer */
        if (create_stack(&s, sizeof(int), print_int, MAX_OPS))
            return -1;
        assert(-1 == pop(&s, (void *) &n));
        print_int(&n);
        for (i = 2; i < ac; i++) {
            n = atoi(av[i]);
            if (-1 == push(&s, (void *) &n))
                fprintf(stderr, "push %s failed\n", av[i]);
            print_stack(&s);
        }
        for (i = 0; i < ac-1; i++) {
            if (-1 == pop(&s, (void *) &n))
                fprintf(stderr, "pop failed (i = %d)\n", i);
            else print_int((void *) &n); 
           print_stack(&s);
        }
        break;

    case 'f': /*double */
        if (create_stack(&s, sizeof(double), print_double, MAX_OPS))
            return -1;
        assert(-1 == pop(&s, (void *) &f));
        print_double(&f);
        for (i = 2; i < ac; i++) {
            f = atof(av[i]);
            if (-1 == push(&s, (void *) &f))
                fprintf(stderr, "push %s failed\n", av[i]);
            print_stack(&s);
        }
        for (i = 2; i < ac; i++) {
            if (-1 == pop(&s, (void *) &f))
                fprintf(stderr, "pop failed (i = %d)\n", i);
            else print_double((void *) &f);
            print_stack(&s);
        }
        break;

    case 's': /* string */
        if (create_stack(&s, sizeof(double), print_string, MAX_OPS))
            return -1;
        assert(-1 == pop(&s, (void *) &f));
        print_double(&f);
        for (i = 2; i < ac; i++) {
            if (-1 == push(&s, (void *) &(av[i])))
                fprintf(stderr, "push %s failed\n", av[i]);
            print_stack(&s);
        }
        for (i = 2; i < ac; i++) {
            if (-1 == pop(&s, (void *) &str))
                fprintf(stderr, "pop failed (i = %d)\n", i);
            else print_string((void *) &str);
            print_stack(&s);
        }
        break;

    default:
        fprintf(stderr, "Unknown type %s\n", av[1]);
        break;
    }

    delete_stack(&s);
    return 0;
}
