add linkedlist variant
[bf.git] / bfll.c
diff --git a/bfll.c b/bfll.c
new file mode 100644 (file)
index 0000000..dfbc456
--- /dev/null
+++ b/bfll.c
@@ -0,0 +1,100 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define die(s, as...) {fprintf(stderr, s, ## as); return EXIT_FAILURE;}
+#define check_fail(v, s, f) if((v) == f) die("%s(): %s\n", s, strerror(errno))
+#define check_null(v, s) check_fail(v, s, NULL)
+
+#define INITIALBUFSIZE 2
+
+struct buf {
+       char v;
+       struct buf *n, *p;
+};
+
+struct cs {
+       long pl;
+       struct cs *next;
+};
+
+int main(int argc, char *argv[])
+{
+       size_t depth;
+       struct buf *p;
+       struct cs *temp, *cs;
+       FILE *in;
+
+       if(argc != 2)
+               die("Usage: %s PROGRAM\n", argv[0]);
+   
+       check_null(in = fopen(argv[1], "r"), "fopen");
+       check_null(p = calloc(sizeof (struct buf), 1), "calloc");
+
+       while (1){
+               switch (fgetc(in)){
+               case EOF:
+                       check_fail(fclose(in), "fclose", -1);
+                       while(p->p != NULL)
+                               p = p->p;
+                       while(p->n != NULL)
+                               free((p = p->n)->p);
+                       free(p);
+                       return EXIT_SUCCESS;
+               case '>':
+                       if(p->n == NULL){
+                               check_null(p->n = calloc(
+                                       sizeof (struct buf), 1), "calloc");
+                               p->n->p = p;
+                       }
+                       p = p->n;
+                       break;
+               case '<':
+                       if(p->p == NULL){
+                               check_null(p->p = calloc(
+                                       sizeof (struct buf), 1), "calloc");
+                               p->p->n = p;
+                       }
+                       p = p->p;
+                       break;
+               case '+':
+                       ++(p->v);
+                       break;
+               case '-':
+                       --(p->v);
+                       break;
+               case '.':
+                       putchar(p->v);
+                       break;
+               case ',':
+                       p->v = getchar();
+                       break;
+               case '[':
+                       if (p->v){
+                               temp = cs;
+                               check_null(cs = malloc(
+                                       sizeof(struct cs)), "malloc");
+                               cs->next = temp;
+                               check_fail(cs->pl = ftell(in), "ftell", -1);
+                       } else {
+                               depth = 1;
+                               while (depth > 0){
+                                       switch (fgetc(in)){
+                                       case ']':
+                                               depth--;
+                                               break;
+                                       case '[':
+                                               depth++;
+                                       }
+                               }
+                       }
+                       break;
+               case ']':
+                       check_fail(fseek(in, cs->pl-1, SEEK_SET), "fseek", -1);
+                       temp = cs;
+                       cs = cs->next;
+                       free(temp);
+               }
+       }
+}