#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 nest {
long pos;
int main(int argc, char *argv[])
{
- size_t offset, stacksize;
+ size_t offset, stacksize, depth;
char *buf, *ptr;
struct nest *temp, *stack;
FILE *in;
if(argc != 2){
- fprintf(stderr, "Usage: %s PROGRAM\n", argv[0]);
- return EXIT_FAILURE;
+ die("Usage: %s PROGRAM\n", argv[0]);
}
- if((buf = malloc(stacksize = 1)) == NULL){
- perror("malloc");
- return EXIT_FAILURE;
- }
- buf[0] = 0;
+ check_null(in = fopen(argv[1], "r"), "fopen");
+ check_null(buf = calloc(stacksize = INITIALBUFSIZE, 1), "calloc");
ptr = buf;
- if((in = fopen(argv[1], "r")) == NULL){
- perror("fopen");
- return EXIT_FAILURE;
- }
-
while(1){
switch(fgetc(in)){
case EOF:
free(buf);
+ check_fail(fclose(in), "fclose", -1);
return EXIT_SUCCESS;
case '>':
- ++ptr;
- if(ptr >= buf+stacksize){
+ if(++ptr >= buf+stacksize){
offset = ptr-buf;
- if((buf = realloc(buf, stacksize *= 2)) == NULL){
- perror("realloc");
- return EXIT_FAILURE;
- }
+ check_null(buf = realloc(buf, stacksize *=2), "realloc");
ptr = buf+offset;
memset(ptr, 0, stacksize/2);
}
break;
case '<':
- if(ptr == buf){
- fprintf(stderr, "There is no stack position -1...\n");
- return EXIT_FAILURE;
+ if(ptr-- == buf){
+ die("There is no stack position -1\n");
}
- --ptr;
break;
case '+':
++*ptr;
case '[':
if(*ptr){
temp = stack;
- if((stack = malloc(sizeof(struct nest))) == NULL){
- perror("realloc");
- return EXIT_FAILURE;
- }
+ check_null(stack = malloc(sizeof(struct nest)), "malloc");
stack->next = temp;
- if((stack->pos = ftell(in)) == -1){
- perror("ftell");
- return EXIT_FAILURE;
- }
+ check_fail(stack->pos = ftell(in), "ftell", -1);
} else {
- while(fgetc(in) != ']');
+ depth = 1;
+ while(depth > 0){
+ switch(fgetc(in)){
+ case ']':
+ depth--;
+ break;
+ case '[':
+ depth++;
+ }
+ }
}
break;
case ']':
- if(fseek(in, stack->pos-1, SEEK_SET) == -1){
- perror("fseek");
- return EXIT_FAILURE;
- }
+ check_fail(fseek(in, stack->pos-1, SEEK_SET), "fseek", -1);
temp = stack;
stack = stack->next;
free(temp);
- break;
- default:
- break;
}
}
}