#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memory.h"

/* ----------------------------------------------------- */

void addEntry (char* name,long long address,long long size)
{
  mapPtr p = (mapPtr) malloc(sizeof(struct mapEntry));
  p->name = name;
  p->address = address;
  p->size = size;
  p->next = MEMORY.info;
  MEMORY.info = p;
}

/* ----------------------------------------------------- */

void initializeMemory (void)
{
  MEMORY.info = NULL;
  MEMORY.nextAddress = (long long) 1;
  // note: memory address 0 is special! (i.e. NULL pointer)
}

long long getNextAddress (void)
{
  return MEMORY.nextAddress;
}

void _DEFINE (char* name,klunk value)
{
  // reserves space for identifier and initializes data
  long long index = MEMORY.nextAddress;
  addEntry (name,index,1);
  MEMORY.data[index] = value;
  MEMORY.nextAddress += 1;
}

void _RESERVE (char* name,long long size)
{
  // reserves specified space for identifier
  // but no initialization
  long long index = MEMORY.nextAddress;
  addEntry (name,index,size);
  MEMORY.nextAddress += size;
}

long long memoryAddress (char* ident)
{
  mapPtr p = MEMORY.info;
  while (p != NULL)
    if (strcmp (p->name,ident) == 0)
      return p->address;
    else
      p = p->next;
  return -1;
}

klunk peek (long long address)
{
  return MEMORY.data[address];
}

void poke (long long address,klunk data)
{
  MEMORY.data[address] = data;
}


void displayMemory (void)
{
  // display static memory (0 .. nextAddress-1)
  printf ("MEMORY STORAGE\n");
  for (long long i = 1;i < MEMORY.nextAddress;++i)
  {
    printf ("%7d ",i);
    show_hex (MEMORY.data[i]);
    printf ("\n");
  }
  printf ("\n");
}

void displayMap (void)
{
  printf ("MEMORY MAP\n");
  mapPtr p = MEMORY.info;
  if (p != NULL)
    reverseDisplay (p);
  printf ("\n");
}

void displayNext (void)
{
  printf ("NEXT ADDRESS: %d\n\n",MEMORY.nextAddress);
}

void displayStack (long long stackTop)
{
  for (long long i = MAXMEM-1;i >= stackTop;--i)
  {
    printf ("%7d ",i);
    show_hex (MEMORY.data[i]);
    printf ("\n");
  }
  printf ("\n");
}

/* ----------------------------------------------------- */

void reverseDisplay (mapPtr p)
{
  if(p != NULL)
  {
    reverseDisplay (p->next);
    printf ("%15s %7d %7d\n",p->name,p->address,p->size);
  }
}

/* ----------------------------------------------------- */
