/* License: AGPLv3 or later. https://www.gnu.org/licenses/licenses.html
 * 
 * Exercise 8 - Dynamic Stack (Week 9)
 * Name: Manish
 * Student Login: *****
 * 
 * Compile as:
 * $ gcc -std=c11 -Wall -o ex8 ex8.c
 */

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

int* stack = NULL;
int index = -1;
int size = 0;

void push(int n);
int pop();
int top();
bool isEmpty();
int max(int i, int j);

int main(void)
{
    printf("Enter file name: ");
    // Assuming filename/file path will not be longer than 256 characters
    char filename[257];
    scanf("%s", filename);

    FILE* file = fopen(filename, "r");
    if (!file)
    {
        perror(filename);
        exit(EXIT_FAILURE);
    }

    if (fscanf(file, " %d ", &size) != EOF)
    {
        stack = malloc(sizeof(int) * size);
        if (size > 0 && stack == NULL)
        {
            fprintf(stderr, "Failed to allocate memory\n");
            return 1;
        }
    }

    // Read and push integers to stack
    char instruction[5];
    int n;
    while (fscanf(file, " %4s ", instruction) != EOF)
    {
        if (strcmp("push", instruction) == 0)
        {
            // whitespaces around to skip them inc. newlines
            if (fscanf(file, " %d ", &n) != EOF)
                push(n);
        }
        else
            n = pop();
    }

    printf("Stack contains %d entries.\n", index + 1);

    fclose(file);
    free(stack);

    return 0;
}

void push(int n)
{
    if (index == size - 1)
    {
        // max() in case original size is 0
        int new_size = max(size * 2, 1);
        int* new_stack = malloc(sizeof(int) * new_size);
        if (new_stack == NULL)
        {
            fprintf(
                stderr,
                "Failed to double stack from %d to %d. Not pushing %d.\n",
                size,
                new_size,
                n);
            return;
        }
        printf("Stack doubled from %d to %d.\n", size, new_size);
        memcpy(new_stack, stack, size*sizeof(int));
        free(stack);
        stack = new_stack;
        size = new_size;
    }
    stack[++index] = n;
}

int pop()
{
    if (isEmpty())
    {
        return -1;
    }
    return stack[index--];
}

bool isEmpty()
{
    return index < 0;
}

int max(int i, int j)
{
    return (i > j) ? i : j;
}
