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

/*
 * Exercises SDCC's malloc / free.  The library pulls in heap.rel + malloc.rel
 * from z80.lib automatically and inits the heap from crt0's _GSINIT chain.
 * Default heap size is 1023 bytes — see docs/TODO.md for plans to grow it.
 */

int main(void)
{
    puts("malloc test:");

    /* small allocations */
    char *a = (char *)malloc(20);
    char *b = (char *)malloc(40);
    char *c = (char *)malloc(60);

    printf("  a = %p\n", a);
    printf("  b = %p\n", b);
    printf("  c = %p\n", c);

    if (a && b && c) {
        strcpy(a, "first");
        strcpy(b, "second-medium-length");
        strcpy(c, "third-and-the-longest-of-them-all");
        printf("  a: \"%s\"\n", a);
        printf("  b: \"%s\"\n", b);
        printf("  c: \"%s\"\n", c);
    } else {
        puts("  one of the allocations FAILED");
    }

    /* free b, alloc smaller — should fit in the b-shaped hole */
    free(b);
    char *d = (char *)malloc(15);
    printf("  after free(b), d = %p (expected near b)\n", d);
    if (d) {
        strcpy(d, "reused");
        printf("  d: \"%s\"\n", d);
    }

    /* drain a larger allocation to see when malloc actually says no */
    int total = 0;
    int count = 0;
    for (;;) {
        void *p = malloc(64);
        if (!p) break;
        total += 64;
        count++;
    }
    printf("  alloc'd %d x 64-byte blocks before failure (total %d bytes)\n",
           count, total);

    free(a);
    free(c);
    free(d);
    puts("");
    puts("Press any key to exit.");
    (void)getchar();
    return 0;
}
