|
- /* linked-list-test.c - singly linked list on the C64, built with cc65
- *
- * Build:
- * cl65 -t c64 -O -o linked-list-test.prg linked-list-test.c
- *
- * Exercises malloc()/free()-backed linked list operations (append,
- * count, sum, search, delete, reverse, free) at sizes from 1000 to
- * 2000 nodes, then runs an allocator capacity test to show how many
- * 4-byte nodes actually fit in real C64 RAM under this cc65 memory
- * config (program loads at $0801, heap tops out at $D000).
- */
-
- #include <stdlib.h>
- #include <conio.h>
- #include <c64.h>
-
- typedef struct Node {
- int value;
- struct Node *next;
- } Node;
-
- /* ---- basic list operations ------------------------------------- */
-
- /* Appends 1..count to a new list. Returns NULL (and frees any partial
- list) if malloc() runs out of memory partway through. */
- static Node *build_list(unsigned int count)
- {
- Node *head = NULL, *tail = NULL, *n;
- unsigned int i;
-
- for (i = 0; i < count; i++) {
- n = malloc(sizeof(Node));
- if (!n) {
- while (head) { n = head; head = head->next; free(n); }
- return NULL;
- }
- n->value = (int)(i + 1);
- n->next = NULL;
- if (head) tail->next = n; else head = n;
- tail = n;
- }
- return head;
- }
-
- static unsigned int count_list(Node *head)
- {
- unsigned int c = 0;
- while (head) { c++; head = head->next; }
- return c;
- }
-
- static long sum_list(Node *head)
- {
- long s = 0;
- while (head) { s += head->value; head = head->next; }
- return s;
- }
-
- static Node *list_find(Node *head, int value)
- {
- while (head) {
- if (head->value == value) return head;
- head = head->next;
- }
- return NULL;
- }
-
- /* Removes the first node matching value. Returns 1 if removed. */
- static unsigned char list_delete(Node **headp, int value)
- {
- Node *prev = NULL, *cur = *headp;
- while (cur) {
- if (cur->value == value) {
- if (prev) prev->next = cur->next; else *headp = cur->next;
- free(cur);
- return 1;
- }
- prev = cur;
- cur = cur->next;
- }
- return 0;
- }
-
- static void list_reverse(Node **headp)
- {
- Node *prev = NULL, *cur = *headp, *next;
- while (cur) {
- next = cur->next;
- cur->next = prev;
- prev = cur;
- cur = next;
- }
- *headp = prev;
- }
-
- static void free_list(Node *head)
- {
- Node *n;
- while (head) { n = head; head = head->next; free(n); }
- }
-
- /* ---- one pass of tests at a given size --------------------------- */
-
- static unsigned char test_size(unsigned int n)
- {
- Node *head;
- unsigned int c;
- long s, expected;
- int mid;
- unsigned char ok = 1;
-
- head = build_list(n);
- if (!head) {
- textcolor(COLOR_RED);
- cprintf("N=%4u ALLOC FAIL\n\r", n);
- return 0;
- }
-
- c = count_list(head);
- s = sum_list(head);
- expected = ((long)n * (n + 1)) / 2;
- if (c != n || s != expected) ok = 0;
-
- mid = (int)(n / 2);
- if (!list_find(head, mid)) ok = 0;
- if (list_find(head, (int)(n + 500))) ok = 0;
-
- if (!list_delete(&head, mid)) ok = 0;
- if (list_find(head, mid)) ok = 0;
- if (count_list(head) != n - 1) ok = 0;
-
- list_reverse(&head);
- if (!head || head->value != (int)n) ok = 0;
-
- free_list(head);
-
- textcolor(ok ? COLOR_GREEN : COLOR_RED);
- cprintf("N=%4u %s\n\r", n, ok ? "PASS" : "FAIL");
- return ok;
- }
-
- /* ---- how many nodes really fit in RAM? --------------------------- */
-
- static void capacity_test(void)
- {
- Node *head = NULL, *tail = NULL, *n;
- unsigned int count = 0;
-
- textcolor(COLOR_WHITE);
- cprintf("\n\rCAPACITY TEST (malloc until NULL)...\n\r");
-
- for (;;) {
- n = malloc(sizeof(Node));
- if (!n) break;
- n->value = (int)count;
- n->next = NULL;
- if (head) tail->next = n; else head = n;
- tail = n;
- count++;
- }
-
- textcolor(COLOR_YELLOW);
- cprintf("MAX NODES ALLOCATED: %u\n\r", count);
- free_list(head);
- }
-
- /* ---- driver -------------------------------------------------------- */
-
- int main(void)
- {
- static const unsigned int sizes[5] = { 1000, 1250, 1500, 1750, 2000 };
- unsigned char i, passed = 0;
-
- clrscr();
- bgcolor(COLOR_BLACK);
- bordercolor(COLOR_BLACK);
- textcolor(COLOR_CYAN);
- cprintf("C64 LINKED LIST TEST (cc65)\n\r");
- cprintf("===========================\n\r");
- textcolor(COLOR_WHITE);
- cprintf("append/count/sum/find/delete/reverse\n\r\n\r");
-
- for (i = 0; i < 5; i++) {
- passed += test_size(sizes[i]);
- }
-
- textcolor(COLOR_WHITE);
- cprintf("\n\r%u/5 SIZE TESTS PASSED\n\r", passed);
-
- capacity_test();
-
- textcolor(COLOR_CYAN);
- cprintf("\n\rDONE - PRESS ANY KEY\n\r");
- cgetc();
-
- bgcolor(COLOR_BLUE);
- bordercolor(COLOR_LIGHTBLUE);
- return 0;
- }
|