#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);
}
}
}