You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

200 lines
4.7KB

  1. /* linked-list-test.c - singly linked list on the C64, built with cc65
  2. *
  3. * Build:
  4. * cl65 -t c64 -O -o linked-list-test.prg linked-list-test.c
  5. *
  6. * Exercises malloc()/free()-backed linked list operations (append,
  7. * count, sum, search, delete, reverse, free) at sizes from 1000 to
  8. * 2000 nodes, then runs an allocator capacity test to show how many
  9. * 4-byte nodes actually fit in real C64 RAM under this cc65 memory
  10. * config (program loads at $0801, heap tops out at $D000).
  11. */
  12. #include <stdlib.h>
  13. #include <conio.h>
  14. #include <c64.h>
  15. typedef struct Node {
  16. int value;
  17. struct Node *next;
  18. } Node;
  19. /* ---- basic list operations ------------------------------------- */
  20. /* Appends 1..count to a new list. Returns NULL (and frees any partial
  21. list) if malloc() runs out of memory partway through. */
  22. static Node *build_list(unsigned int count)
  23. {
  24. Node *head = NULL, *tail = NULL, *n;
  25. unsigned int i;
  26. for (i = 0; i < count; i++) {
  27. n = malloc(sizeof(Node));
  28. if (!n) {
  29. while (head) { n = head; head = head->next; free(n); }
  30. return NULL;
  31. }
  32. n->value = (int)(i + 1);
  33. n->next = NULL;
  34. if (head) tail->next = n; else head = n;
  35. tail = n;
  36. }
  37. return head;
  38. }
  39. static unsigned int count_list(Node *head)
  40. {
  41. unsigned int c = 0;
  42. while (head) { c++; head = head->next; }
  43. return c;
  44. }
  45. static long sum_list(Node *head)
  46. {
  47. long s = 0;
  48. while (head) { s += head->value; head = head->next; }
  49. return s;
  50. }
  51. static Node *list_find(Node *head, int value)
  52. {
  53. while (head) {
  54. if (head->value == value) return head;
  55. head = head->next;
  56. }
  57. return NULL;
  58. }
  59. /* Removes the first node matching value. Returns 1 if removed. */
  60. static unsigned char list_delete(Node **headp, int value)
  61. {
  62. Node *prev = NULL, *cur = *headp;
  63. while (cur) {
  64. if (cur->value == value) {
  65. if (prev) prev->next = cur->next; else *headp = cur->next;
  66. free(cur);
  67. return 1;
  68. }
  69. prev = cur;
  70. cur = cur->next;
  71. }
  72. return 0;
  73. }
  74. static void list_reverse(Node **headp)
  75. {
  76. Node *prev = NULL, *cur = *headp, *next;
  77. while (cur) {
  78. next = cur->next;
  79. cur->next = prev;
  80. prev = cur;
  81. cur = next;
  82. }
  83. *headp = prev;
  84. }
  85. static void free_list(Node *head)
  86. {
  87. Node *n;
  88. while (head) { n = head; head = head->next; free(n); }
  89. }
  90. /* ---- one pass of tests at a given size --------------------------- */
  91. static unsigned char test_size(unsigned int n)
  92. {
  93. Node *head;
  94. unsigned int c;
  95. long s, expected;
  96. int mid;
  97. unsigned char ok = 1;
  98. head = build_list(n);
  99. if (!head) {
  100. textcolor(COLOR_RED);
  101. cprintf("N=%4u ALLOC FAIL\n\r", n);
  102. return 0;
  103. }
  104. c = count_list(head);
  105. s = sum_list(head);
  106. expected = ((long)n * (n + 1)) / 2;
  107. if (c != n || s != expected) ok = 0;
  108. mid = (int)(n / 2);
  109. if (!list_find(head, mid)) ok = 0;
  110. if (list_find(head, (int)(n + 500))) ok = 0;
  111. if (!list_delete(&head, mid)) ok = 0;
  112. if (list_find(head, mid)) ok = 0;
  113. if (count_list(head) != n - 1) ok = 0;
  114. list_reverse(&head);
  115. if (!head || head->value != (int)n) ok = 0;
  116. free_list(head);
  117. textcolor(ok ? COLOR_GREEN : COLOR_RED);
  118. cprintf("N=%4u %s\n\r", n, ok ? "PASS" : "FAIL");
  119. return ok;
  120. }
  121. /* ---- how many nodes really fit in RAM? --------------------------- */
  122. static void capacity_test(void)
  123. {
  124. Node *head = NULL, *tail = NULL, *n;
  125. unsigned int count = 0;
  126. textcolor(COLOR_WHITE);
  127. cprintf("\n\rCAPACITY TEST (malloc until NULL)...\n\r");
  128. for (;;) {
  129. n = malloc(sizeof(Node));
  130. if (!n) break;
  131. n->value = (int)count;
  132. n->next = NULL;
  133. if (head) tail->next = n; else head = n;
  134. tail = n;
  135. count++;
  136. }
  137. textcolor(COLOR_YELLOW);
  138. cprintf("MAX NODES ALLOCATED: %u\n\r", count);
  139. free_list(head);
  140. }
  141. /* ---- driver -------------------------------------------------------- */
  142. int main(void)
  143. {
  144. static const unsigned int sizes[5] = { 1000, 1250, 1500, 1750, 2000 };
  145. unsigned char i, passed = 0;
  146. clrscr();
  147. bgcolor(COLOR_BLACK);
  148. bordercolor(COLOR_BLACK);
  149. textcolor(COLOR_CYAN);
  150. cprintf("C64 LINKED LIST TEST (cc65)\n\r");
  151. cprintf("===========================\n\r");
  152. textcolor(COLOR_WHITE);
  153. cprintf("append/count/sum/find/delete/reverse\n\r\n\r");
  154. for (i = 0; i < 5; i++) {
  155. passed += test_size(sizes[i]);
  156. }
  157. textcolor(COLOR_WHITE);
  158. cprintf("\n\r%u/5 SIZE TESTS PASSED\n\r", passed);
  159. capacity_test();
  160. textcolor(COLOR_CYAN);
  161. cprintf("\n\rDONE - PRESS ANY KEY\n\r");
  162. cgetc();
  163. bgcolor(COLOR_BLUE);
  164. bordercolor(COLOR_LIGHTBLUE);
  165. return 0;
  166. }

Powered by TurnKey Linux.