#include <stdio.h>

#define MEM 100000
char memory[MEM];
static int nextavailable = 0;

/* management block */
typedef struct b {
  struct b *next;  
  int size;  /* available space */
  char data[0];
} b_t;

static b_t *freelist;

void *malloc(size_t size) {
  b_t *b, *prev;

  /* search free list (created by imagined free()) */  
  if (freelist) {
    prev = NULL;
    for (b = freelist; b; b = b->next) {
      if (b->size >= size) {
        /* remove from freelist */
        if (prev) prev->next = b->next;
        else freelist = b->next;
        return &b->data[0];
      }
      prev = b;
    }   
  } else {
    /* if nothing on freelist, get block */
    if (nextavailable + size >= MEM) {
      /* out of space */
      return NULL;
    } else {
      /* round up size to nearest multiple of 4 */
      b = (b_t *)&memory[nextavailable];
      b->size = (size + 3) & 0xfffffffc;
      nextavailable += b->size + sizeof(b_t);
      b->next = NULL;
      return &b->data[0];
    }
  }
  return NULL;
}

int main(int argc, char *argv[]) {
  void *p;

  printf("memory %p\n", memory);
  p = malloc(1000);
  printf("p=%p, nextavailable = %d\n", p, nextavailable);
  p = malloc(200);
  printf("p=%p, nextavailable = %d\n", p, nextavailable);
  p = malloc(99);
  printf("p=%p, nextavailable = %d\n", p, nextavailable);

  return 0;
}

