#include <stdlib.h>
#include <syscall.h>

#define ALIGN(size) (((size) + 3) & ~3)
#define HEADER_SIZE sizeof(struct Header)

struct Header {
    size_t size;
    int is_free;
    struct Header* next;
};

static struct Header* free_list_head = NULL;

static struct Header* find_free_block(struct Header** last, size_t size) {
    struct Header* current = free_list_head;
    while (current && !(current->is_free && current->size >= size)) {
        *last = current;
        current = current->next;
    }
    return current;
}

static struct Header* request_space(struct Header* last, size_t size) {
    struct Header* block = sbrk(0);
    void* request = sbrk(size + HEADER_SIZE);
    
    if (request == (void*)-1) {
        return NULL;
    }
    
    if (last) {
        last->next = block;
    }
    
    block->size = size;
    block->next = NULL;
    block->is_free = 0;
    return block;
}

void* malloc(size_t size) {
    if (size <= 0) {
        return NULL;
    }
    
    size = ALIGN(size);
    
    if (free_list_head == NULL) {
        struct Header* block = request_space(NULL, size);
        if (!block) return NULL;
        free_list_head = block;
        return (void*)(block + 1);
    }
    
    struct Header* last = free_list_head;
    struct Header* block = find_free_block(&last, size);
    
    if (block) {
        block->is_free = 0;
    } else {
        block = request_space(last, size);
        if (!block) return NULL;
    }
    
    return (void*)(block + 1);
}

void free(void* ptr) {
    if (!ptr) return;
    
    struct Header* block = (struct Header*)ptr - 1;
    block->is_free = 1;
}