/* C11. singly linked list, owned by head. */
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct Node { int value; struct Node *next; } Node;
static bool prepend(Node **head, int value)
{
    Node *node = malloc(sizeof *node);
    if (node == NULL) return false; /* Leave the existing list unchanged. */
    node->value = value; node->next = *head; *head = node;
    return true;
}
/* Remove the first matching value; pointer-to-pointer also handles the head. */
static bool remove_first(Node **head, int value)
{
    Node **link = head;
    while (*link != NULL && (*link)->value != value) link = &(*link)->next;
    if (*link == NULL) return false;
    Node *victim = *link;
    *link = victim->next;
    free(victim);
    return true;
}
static const Node *find(const Node *head, int value)
{
    while (head != NULL && head->value != value) head = head->next;
    return head;
}
static void clear(Node **head)
{
    while (*head != NULL) {
        Node *next = (*head)->next;
        free(*head); *head = next;
    }
}
int main(void)
{
    Node *head = NULL;
    assert(!remove_first(&head, 10)); assert(find(head, 10) == NULL);
    for (int i = 4; i >= 1; --i) {
        if (!prepend(&head, i * 10)) { clear(&head); return EXIT_FAILURE; }
    }
    assert(find(head, 30) != NULL);
    assert(remove_first(&head, 10)); /* head */
    assert(remove_first(&head, 30)); /* middle */
    assert(!remove_first(&head, 99));
    printf("List:");
    for (const Node *p = head; p != NULL; p = p->next) printf(" %d", p->value);
    putchar('\n');
    assert(remove_first(&head, 40)); /* tail */
    assert(remove_first(&head, 20)); /* sole node */
    assert(head == NULL);
    assert(prepend(&head, 5)); assert(prepend(&head, 5));
    assert(remove_first(&head, 5) && head != NULL && head->value == 5);
    clear(&head); clear(&head); assert(head == NULL);
    puts("linked-list tests passed");
    return EXIT_SUCCESS;
}
