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

struct IStack {
      int maxSize;
      int index;
      int* start;
      int nSizeUnits;
  } IStack;
  const int sizeUnit =2;

struct IStack* createIntStack() {
        struct IStack* p;
        p = (struct IStack*) malloc(sizeof(struct IStack));
        if (p == NULL) {printf("error in malloc createStack\n");  }
        p->nSizeUnits =1;
        p->maxSize = sizeUnit*p->nSizeUnits;

        p->start = (int*) malloc(p->maxSize*sizeof(int));
        if (p->start == NULL) {printf("error in malloc createIntStack\n");   }
        int i;  // initialize all to zero
        for(i=0; i< p->maxSize; i++) {
            p->start[i]=0;
        }
        p->index = p->maxSize-1;
        return p;

   }
void push(struct IStack* p, int value){
    if (p->index >=0 ){ p->start[p->index] = value; p->index--;
    }
    else {    //printf("out of bound index push\n");
        int* pCopy;

        p->nSizeUnits++;
        int oldSize = p->maxSize;
        p->maxSize = sizeUnit  * p->nSizeUnits;

        pCopy = (int*) malloc(p->maxSize*sizeof(int));

        if (pCopy == NULL) {printf("error in malloc pushIntStack\n");   }
        // initialize, only the new part

        int i;
        for( i=0; i<sizeUnit; i++){
            pCopy[i] =  0;
        }
        // copy p on pCopy
        for( i=0; i<oldSize; i++){
            pCopy[i + sizeUnit] =  p->start[i] ;
        }
        p->index += sizeUnit;  // recount index
        pCopy[p->index ] =  value;
        p->index--;

        int* toBefreed = p->start;
        p->start = pCopy;
        free(toBefreed);
    }

   }

int pop(struct IStack* p){
   if (p->index == p->maxSize-1){printf("pop with empty stack\n"); return;}  // empty case
   int r = p->start[p->index+1];
    p->start[p->index+1] = 0;  // re initialize to zero when element popped
   p->index++;
   return r;

   }


   void  freeIntStack (struct IStack* p){
       free(p->start);
       free(p);
      }
void printIntStack(struct IStack* p){
      int index ;
      printf("printing stack %p\n", p);
      for(index=0; index< p->maxSize; index++)
      printf("%d, ",  p->start[index]);
      printf("end %p\n", p);
      }

int main(int argc, char *argv[])
{
    struct IStack * s1;
    s1 = createIntStack();
    printIntStack(s1);
    push(s1, 1);
    printIntStack(s1);
    push(s1, 10);
    printIntStack(s1);
    push(s1, 20);
    push(s1, 21);
    push(s1, 22);
    push(s1, 23);
    printIntStack(s1);

//     s1->start[33] = 17;  // FORBIDDEN
    push(s1, 17);  // YES
    printIntStack(s1);

    int r = pop(s1);  // return 17
    printf("result of pop is %d\n" , r);
    printIntStack(s1);
    push(s1, 12);
        printIntStack(s1);

    r = pop(s1); printf("result of pop is %d\n" , r);  // return 12
    printIntStack(s1);

    r = pop(s1); printf("result of pop is %d\n" , r);   // return 23
    printIntStack(s1);
    pop(s1); pop(s1); pop(s1);pop(s1);pop(s1);pop(s1);pop(s1);
    printIntStack(s1);
    freeIntStack(s1);




  system("PAUSE");
  return 0;
}

