please @camilstaps
[bf.git] / bf.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <errno.h>
5
6 #define die(s, as...) {fprintf(stderr, s, ## as); return EXIT_FAILURE;}
7 #define check_fail(v, s, f) if((v) == f) die("%s(): %s\n", s, strerror(errno))
8 #define check_null(v, s) check_fail(v, s, NULL)
9
10 #define INITIALBUFSIZE 2
11
12 struct cs {
13 long pl;
14 struct cs *next;
15 };
16
17 int main(int argc, char *argv[])
18 {
19 size_t offset, bufsize, depth;
20 char *buf, *ptr;
21 struct cs *temp, *cs;
22 FILE *in;
23
24 if(argc != 2)
25 die("Usage: %s PROGRAM\n", argv[0]);
26
27 check_null(in = fopen(argv[1], "r"), "fopen");
28 check_null(buf = calloc(bufsize = INITIALBUFSIZE, 1), "calloc");
29 ptr = buf;
30
31 while (1){
32 switch (fgetc(in)){
33 case EOF:
34 free(buf);
35 check_fail(fclose(in), "fclose", -1);
36 return EXIT_SUCCESS;
37 case '>':
38 if (++ptr >= buf+bufsize){
39 offset = ptr-buf;
40 check_null(buf = realloc(buf, bufsize *=2),
41 "realloc");
42 ptr = buf+offset;
43 memset(ptr, 0, bufsize/2);
44 }
45 break;
46 case '<':
47 if (ptr-- == buf)
48 die("There is no stack position -1\n");
49 break;
50 case '+':
51 ++*ptr;
52 break;
53 case '-':
54 --*ptr;
55 break;
56 case '.':
57 putchar(*ptr);
58 break;
59 case ',':
60 *ptr = getchar();
61 break;
62 case '[':
63 if (*ptr){
64 temp = cs;
65 check_null(cs = malloc(sizeof(struct cs)),
66 "malloc");
67 cs->next = temp;
68 check_fail(cs->pl = ftell(in), "ftell", -1);
69 } else {
70 depth = 1;
71 while (depth > 0){
72 switch (fgetc(in)){
73 case ']':
74 depth--;
75 break;
76 case '[':
77 depth++;
78 }
79 }
80 }
81 break;
82 case ']':
83 check_fail(fseek(in, cs->pl-1, SEEK_SET), "fseek", -1);
84 temp = cs;
85 cs = cs->next;
86 free(temp);
87 }
88 }
89 }