fork(1) download
  1. /* @(#)bf.c
  2.  */
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <errno.h>
  7. #include <string.h>
  8. #include <stdbool.h>
  9.  
  10.  
  11. typedef struct BI_t {
  12. struct BI_t *previous, *next;
  13. char *data;
  14. char visited;
  15. } BrainfuckInstruction;
  16.  
  17.  
  18. typedef bool (*bi_op)(BrainfuckInstruction*);
  19.  
  20. BrainfuckInstruction *bi_make(const char *data);
  21. bool bi_delete(BrainfuckInstruction *instruction);
  22. void bi_foreach(BrainfuckInstruction* start, bi_op f);
  23.  
  24. BrainfuckInstruction *bi_make(const char *data) {
  25. BrainfuckInstruction *instruction = calloc(1, sizeof(BrainfuckInstruction));
  26. if (instruction) {
  27. if ((instruction->data = malloc(strlen(data)))) {
  28. strcpy(instruction->data, data);
  29. } else {
  30. int err = errno;
  31. bi_delete(instruction);
  32. instruction = NULL;
  33. errno = err;
  34. }
  35. }
  36. return instruction;
  37. }
  38.  
  39. bool bi_discard(BrainfuckInstruction *instruction) {
  40. if (instruction->data) {
  41. printf("discarding '%s'\n", instruction->data);
  42. free(instruction->data);
  43. }
  44. free(instruction);
  45. return 1;
  46. }
  47.  
  48. bool bi_delete(BrainfuckInstruction *instruction) {
  49. if (instruction->next) {
  50. instruction->next->previous = instruction->previous;
  51. }
  52. if (instruction->previous) {
  53. instruction->previous->next = instruction->next;
  54. }
  55. bi_discard(instruction);
  56. return 1;
  57. }
  58.  
  59. BrainfuckInstruction* bi_insert_after(BrainfuckInstruction *instruction, BrainfuckInstruction *after) {
  60. instruction->previous = after;
  61. instruction->next = after->next;
  62. after->next = instruction;
  63. if (instruction->next) {
  64. instruction->next->previous = instruction;
  65. }
  66. return instruction;
  67. }
  68.  
  69.  
  70. void bi_foreach(BrainfuckInstruction* start, bi_op f) {
  71. while (start) {
  72. if (! f(start)) { return; }
  73. start = start->next;
  74. }
  75. }
  76.  
  77. bool bi_unvisit(BrainfuckInstruction* instruction) {
  78. if (instruction->visited) {
  79. instruction->visited = 0;
  80. return 1;
  81. }
  82. return 0;
  83. }
  84.  
  85. bool bi_print(BrainfuckInstruction* instruction) {
  86. printf("%s\n", instruction->data);
  87. return 1;
  88. }
  89.  
  90.  
  91.  
  92. typedef struct BS_t {
  93. BrainfuckInstruction *head;
  94. } BrainfuckState;
  95.  
  96. BrainfuckState *bs_make() {
  97. return calloc(1, sizeof(BrainfuckState));
  98. }
  99.  
  100. void bs_delete(BrainfuckState *state) {
  101. bi_foreach(state->head, bi_discard);
  102. free(state);
  103. }
  104.  
  105. void bs_unvisit(BrainfuckState* state) {
  106. bi_foreach(state->head, bi_unvisit);
  107. }
  108.  
  109. void bs_foreach(BrainfuckState* state, bi_op f) {
  110. BrainfuckInstruction *curr = state->head;
  111. while (curr && ! curr->visited) {
  112. curr->visited = 1;
  113. if (! f(curr)) { return ; }
  114. curr = curr->next;
  115. }
  116. bs_unvisit(state);
  117. }
  118.  
  119. void bs_print(BrainfuckState* state) {
  120. bs_foreach(state, bi_print);
  121. }
  122.  
  123.  
  124.  
  125. BrainfuckInstruction * brainfuck_insert_after(BrainfuckState *state, BrainfuckInstruction *after, BrainfuckInstruction *instruction)
  126. {
  127. if (state == NULL || after == NULL || instruction == NULL)
  128. return NULL;
  129.  
  130. BrainfuckInstruction *next = after->next;
  131.  
  132. after->next = instruction;
  133. instruction->previous = after;
  134.  
  135. BrainfuckInstruction *iter = instruction;
  136.  
  137. while (iter != NULL) {
  138. if (iter->next == NULL)
  139. break;
  140. iter = iter->next;
  141. }
  142.  
  143. if (next != NULL) {
  144. next->previous = iter;
  145. iter->next = next;
  146. }
  147. if (state->head == after)
  148. state->head = iter;
  149. return instruction;
  150. }
  151.  
  152. int main(int argc, char **argv) {
  153. BrainfuckInstruction *end;
  154. BrainfuckState *state;
  155.  
  156. state = bs_make();
  157. end = state->head = bi_make("start");
  158. end = bi_insert_after(bi_make("step 1"), end);
  159. end = bi_insert_after(bi_make("step 2"), end);
  160. end = bi_insert_after(bi_make("step 3"), end);
  161. end = bi_insert_after(bi_make("end"), end);
  162.  
  163. BrainfuckInstruction *curr;
  164. curr = bi_make("WHOOP");
  165. bi_insert_after(bi_make("DE"), curr);
  166. bi_insert_after(bi_make("DO"), curr->next);
  167.  
  168.  
  169. brainfuck_insert_after(state, state->head->next, curr);
  170.  
  171.  
  172. printf("\tprinting-\n");
  173. bs_print(state);
  174. printf("\tdeleting-\n");
  175. bs_delete(state);
  176.  
  177. return 0;
  178. }
  179.  
Success #stdin #stdout 0s 2140KB
stdin
Standard input is empty
stdout
	printing-
start
step 1
WHOOP
DE
DO
step 2
step 3
end
	deleting-
discarding 'start'
discarding 'step 1'
discarding 'WHOOP'
discarding 'DE'
discarding 'DO'
discarding 'step 2'
discarding 'step 3'
discarding 'end'