please @camilstaps
[bf.git] / bfll.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 buf {
13 char v;
14 struct buf *n, *p;
15 };
16
17 struct cs {
18 long pl;
19 struct cs *next;
20 };
21
22 int main(int argc, char *argv[])
23 {
24 size_t depth;
25 struct buf *p;
26 struct cs *temp, *cs;
27 FILE *in;
28
29 if(argc != 2)
30 die("Usage: %s PROGRAM\n", argv[0]);
31
32 check_null(in = fopen(argv[1], "r"), "fopen");
33 check_null(p = calloc(sizeof (struct buf), 1), "calloc");
34
35 while (1){
36 switch (fgetc(in)){
37 case EOF:
38 check_fail(fclose(in), "fclose", -1);
39 while(p->p != NULL)
40 p = p->p;
41 while(p->n != NULL)
42 free((p = p->n)->p);
43 free(p);
44 return EXIT_SUCCESS;
45 case '>':
46 if(p->n == NULL){
47 check_null(p->n = calloc(
48 sizeof (struct buf), 1), "calloc");
49 p->n->p = p;
50 }
51 p = p->n;
52 break;
53 case '<':
54 if(p->p == NULL){
55 check_null(p->p = calloc(
56 sizeof (struct buf), 1), "calloc");
57 p->p->n = p;
58 }
59 p = p->p;
60 break;
61 case '+':
62 ++(p->v);
63 break;
64 case '-':
65 --(p->v);
66 break;
67 case '.':
68 putchar(p->v);
69 break;
70 case ',':
71 p->v = getchar();
72 break;
73 case '[':
74 if (p->v){
75 temp = cs;
76 check_null(cs = malloc(
77 sizeof(struct cs)), "malloc");
78 cs->next = temp;
79 check_fail(cs->pl = ftell(in), "ftell", -1);
80 } else {
81 depth = 1;
82 while (depth > 0){
83 switch (fgetc(in)){
84 case ']':
85 depth--;
86 break;
87 case '[':
88 depth++;
89 }
90 }
91 }
92 break;
93 case ']':
94 check_fail(fseek(in, cs->pl-1, SEEK_SET), "fseek", -1);
95 temp = cs;
96 cs = cs->next;
97 free(temp);
98 }
99 }
100 }