please @camilstaps
[bf.git] / bf.c
diff --git a/bf.c b/bf.c
index ef5dd39..189eba9 100644 (file)
--- a/bf.c
+++ b/bf.c
@@ -1,88 +1,89 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
+#include <errno.h>
 
-struct nest {
-       long pos;
-       struct nest *next;
+#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 cs {
+       long pl;
+       struct cs *next;
 };
 
 int main(int argc, char *argv[])
 {
-       size_t offset, stacksize = 1;
-       char *b = malloc(stacksize);
-       b[0] = 0;
-       char *ptr = b;
-       struct nest *t, *callstack = NULL;
+       size_t offset, bufsize, depth;
+       char *buf, *ptr;
+       struct cs *temp, *cs;
        FILE *in;
 
-       if(argc != 2){
-               fprintf(stderr, "Usage: %s PROGRAM\n", argv[0]);
-               return EXIT_FAILURE;
-       }
-       
-       if((in = fopen(argv[1], "r")) == NULL){
-               perror("fopen");
-               return EXIT_FAILURE;
-       }
+       if(argc != 2)
+               die("Usage: %s PROGRAM\n", argv[0]);
+   
+       check_null(in = fopen(argv[1], "r"), "fopen");
+       check_null(buf = calloc(bufsize = INITIALBUFSIZE, 1), "calloc");
+       ptr = buf;
 
-       while(1){
-               switch(fgetc(in)){
-                       case EOF:
-                               free(b);
-                               return EXIT_SUCCESS;
-                       case '>':
-                               ++ptr;
-                               if(ptr >= b+stacksize){
-                                       offset = ptr-b;
-                                       b = realloc(b, stacksize *= 2);
-                                       ptr = b+offset;
-                                       memset(ptr, 0, stacksize/2);
-                               }
-                               break;
-                       case '<':
-                               if(ptr == b){
-                                       fprintf(stderr, "There is no stack position -1...\n");
-                                       return EXIT_FAILURE;
-                               }
-                               --ptr;
-                               break;
-                       case '+':
-                               ++*ptr;
-                               break;
-                       case '-':
-                               --*ptr;
-                               break;
-                       case '.':
-                               putchar(*ptr);
-                               break;
-                       case ',':
-                               *ptr = getchar();
-                               break;
-                       case '[':
-                               if(*ptr){
-                                       t = callstack;
-                                       callstack = malloc(sizeof(struct nest));
-                                       callstack->next = t;
-                                       if((callstack->pos = ftell(in)) == -1){
-                                               perror("ftell");
-                                               return EXIT_FAILURE;
+       while (1){
+               switch (fgetc(in)){
+               case EOF:
+                       free(buf);
+                       check_fail(fclose(in), "fclose", -1);
+                       return EXIT_SUCCESS;
+               case '>':
+                       if (++ptr >= buf+bufsize){
+                               offset = ptr-buf;
+                               check_null(buf = realloc(buf, bufsize *=2),
+                                       "realloc");
+                               ptr = buf+offset;
+                               memset(ptr, 0, bufsize/2);
+                       }
+                       break;
+               case '<':
+                       if (ptr-- == buf)
+                               die("There is no stack position -1\n");
+                       break;
+               case '+':
+                       ++*ptr;
+                       break;
+               case '-':
+                       --*ptr;
+                       break;
+               case '.':
+                       putchar(*ptr);
+                       break;
+               case ',':
+                       *ptr = getchar();
+                       break;
+               case '[':
+                       if (*ptr){
+                               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++;
                                        }
-                               } else {
-                                       while(fgetc(in) != ']');
-                               }
-                               break;
-                       case ']':
-                               if(fseek(in, callstack->pos-1, SEEK_SET) == -1){
-                                       perror("fseek");
-                                       return EXIT_FAILURE;
                                }
-                               t = callstack;
-                               callstack = callstack->next;
-                               free(t);
-                               break;
-                       default:
-                               break;
+                       }
+                       break;
+               case ']':
+                       check_fail(fseek(in, cs->pl-1, SEEK_SET), "fseek", -1);
+                       temp = cs;
+                       cs = cs->next;
+                       free(temp);
                }
        }
 }