/* MEMDEMO.SLC

  Rowan Crowe <rowan@sensation.net.au>

  This program demonstrates how to use the basic tiny/near memory system
  supplied with SLC, which is adapted from MoonRock's well established
  memory manager code.

  It also demonstrates some other library routines.


  compile with:   slc memdemo


  General memory allocation guidelines:

    1. Call tinymeminit() with the size of the stack you want. It will
    return the size of the heap (64k - code - static data - stack) or -1
    if there was a fatal error. This call sets errno (see the include
    file alib/errno.inc). The size of the stack depends on function
    nesting, local variables etc. For a reasonably complex program it
    should probably be 4k or more.

    2. Call malloc() with the size of the block you want. It returns a
    pointer to the block, or -1 if there was a fatal error. This call
    sets errno.

    3. Call free() with the pointer of the previously allocated block to
    release the block back to the free memory pool. This call returns -1
    and sets errno if an error happens.

  Note: it's important to check for errors, especially after malloc.

*/


/* this definition is important for malloc and other routines which set it */
global int errno

/* define our external library functions */
extern int malloc()
extern int tinymeminit()
extern int free()
extern void puts()
extern int input()
extern int uitostr()
extern int hex16()

void main() {
  int rv
  int heapsize
  int sz
  char *p

  puts("Initialising memory...")
  heapsize = tinymeminit(1024)  /* 1024 bytes stack */
  if (heapsize == -1) {
    puts("memory init failed.\n")
    return 0
  }
  puts("OK!\n")

  puts("Available data memory is ")
  /*
     The line below is sneaky, it uses the space occupied by a string
     constant as a buffer! In this case, we don't want to allocate any
     memory just yet (what if it fails? etc), so it's probably the only
     easy way to do it, because SLC doesn't yet support local static
     allocation on the stack.
  */
  puts(uitostr("123456", (heapsize)))
  puts(" bytes\n")

  puts("Allocating 32 bytes...")
  p = malloc(32)
  /* p now contains pointer to allocated memory block or -1 if there was
  some problem */
  if (p == -1) {
    puts("memory allocation failed.\n")
    return 0
  }
  puts("OK!\n")

  puts("\nPlease enter your name: ")
  sz = input(p, 32)
  puts("\nHello ")
  puts(p)
  puts(", pleased to meet you.\n\n")

  puts("Freeing up previously allocated block at 0x")
  puts(hex16(p, p))
  puts("...")
  rv = free(p)  /* free the block */
  if (rv == -1) {
    puts("memory free failed.\n")
    return 0
  }
  puts("OK!\n")

}
