Made debugging clearer: refactored error messages and return codes; warning on non-usable character in file
This commit is contained in:
@@ -1,36 +1,36 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define OP_END 0
|
#define END 0
|
||||||
#define OP_INC_DP 1
|
#define INC_DP 1
|
||||||
#define OP_DEC_DP 2
|
#define DEC_DP 2
|
||||||
#define OP_INC_VAL 3
|
#define INC_VAL 3
|
||||||
#define OP_DEC_VAL 4
|
#define DEC_VAL 4
|
||||||
#define OP_OUT 5
|
#define OUT 5
|
||||||
#define OP_IN 6
|
#define IN 6
|
||||||
#define OP_JMP_FWD 7
|
#define JMP_FWD 7
|
||||||
#define OP_JMP_BCK 8
|
#define JMP_BCK 8
|
||||||
|
|
||||||
#define PROGRAM_SIZE 1048576
|
#define PROGRAM_SIZE 1048576
|
||||||
#define MAX_SIZE 5024291
|
#define MAX_SIZE 5024291
|
||||||
#define DATA_SIZE 1638375
|
#define DATA_SIZE 1638375
|
||||||
|
|
||||||
#define STACK_PUSH(A) (stack[sp++] = A)
|
#define PUSH(A) (stack[sp++] = A)
|
||||||
#define STACK_POP() (stack[--sp])
|
#define POP() (stack[--sp])
|
||||||
#define STACK_EMPTY() (sp == 0)
|
#define EMPTY() (sp == 0)
|
||||||
#define STACK_FULL() (sp == MAX_SIZE)
|
#define FULL() (sp == MAX_SIZE)
|
||||||
|
|
||||||
static inline void die(int code, const char* message){
|
static inline void die(int code, const char* message){
|
||||||
fprintf(stderr, "%s", message);
|
fprintf(stderr, "%s", message);
|
||||||
exit(code);
|
exit(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct instruction_t{
|
struct instruction{
|
||||||
unsigned int operator;
|
unsigned int operator;
|
||||||
unsigned int operand;
|
unsigned int operand;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct instruction_t program[PROGRAM_SIZE];
|
static struct instruction program[PROGRAM_SIZE];
|
||||||
static unsigned int stack[MAX_SIZE];
|
static unsigned int stack[MAX_SIZE];
|
||||||
static unsigned long sp = 0;
|
static unsigned long sp = 0;
|
||||||
|
|
||||||
@@ -39,67 +39,69 @@ void compile(FILE* fp){
|
|||||||
int ip;
|
int ip;
|
||||||
while ((ip = getc(fp)) != EOF && pc < MAX_SIZE){
|
while ((ip = getc(fp)) != EOF && pc < MAX_SIZE){
|
||||||
switch (ip) {
|
switch (ip) {
|
||||||
case '>': program[pc].operator = OP_INC_DP; break;
|
case '>': program[pc].operator = INC_DP; break;
|
||||||
case '<': program[pc].operator = OP_DEC_DP; break;
|
case '<': program[pc].operator = DEC_DP; break;
|
||||||
case '+': program[pc].operator = OP_INC_VAL; break;
|
case '+': program[pc].operator = INC_VAL; break;
|
||||||
case '-': program[pc].operator = OP_DEC_VAL; break;
|
case '-': program[pc].operator = DEC_VAL; break;
|
||||||
case '.': program[pc].operator = OP_OUT; break;
|
case '.': program[pc].operator = OUT; break;
|
||||||
case ',': program[pc].operator = OP_IN; break;
|
case ',': program[pc].operator = IN; break;
|
||||||
case '[':
|
case '[':
|
||||||
program[pc].operator = OP_JMP_FWD;
|
program[pc].operator = JMP_FWD;
|
||||||
if (STACK_FULL())
|
if (FULL())
|
||||||
die(1, "Cannot jump forwards: Stack is full.\n");
|
die(127, "nbfi:compile: Cannot jump forwards: Stack is full.\n");
|
||||||
STACK_PUSH(pc);
|
PUSH(pc);
|
||||||
break;
|
break;
|
||||||
case ']':
|
case ']':
|
||||||
if (STACK_EMPTY())
|
if (EMPTY())
|
||||||
die(1, "Cannot jump backwards: Stack is full.\n");
|
die(127, "nbfi:compile: Cannot jump backwards: Stack is full.\n");
|
||||||
jmp_pc = STACK_POP();
|
jmp_pc = POP();
|
||||||
program[pc].operator = OP_JMP_BCK;
|
program[pc].operator = JMP_BCK;
|
||||||
program[pc].operand = jmp_pc;
|
program[pc].operand = jmp_pc;
|
||||||
program[jmp_pc].operand = pc;
|
program[jmp_pc].operand = pc;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if(ip > 32 && ip < 128)
|
||||||
|
fprintf(stderr, "nbfi:compile: Warning: Unknown command: %c\n", ip);
|
||||||
pc--;
|
pc--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pc++;
|
pc++;
|
||||||
}
|
}
|
||||||
if(!STACK_EMPTY())
|
if(!EMPTY())
|
||||||
die(1, "Program ends with non-empty stack.");
|
die(117, "nbfi:compile: Program ends with non-empty stack.");
|
||||||
if(pc == MAX_SIZE)
|
if(pc == MAX_SIZE)
|
||||||
die(1, "Program exceeds maximum program size.");
|
die(127, "nbfi:compile: Program exceeds maximum program size.");
|
||||||
program[pc].operator = OP_END;
|
program[pc].operator = END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(){
|
void execute(){
|
||||||
unsigned int data[DATA_SIZE], pc = 0;
|
unsigned int data[DATA_SIZE], pc = 0;
|
||||||
unsigned int ptr = DATA_SIZE;
|
unsigned int ptr = DATA_SIZE;
|
||||||
while (--ptr) data[ptr] = 0;
|
while (--ptr) data[ptr] = 0;
|
||||||
while (program[pc].operator != OP_END && ptr < DATA_SIZE){
|
while (program[pc].operator != END && ptr < DATA_SIZE){
|
||||||
switch (program[pc].operator){
|
switch (program[pc].operator){
|
||||||
case OP_INC_DP: ptr++; break;
|
case INC_DP: ptr++; break;
|
||||||
case OP_DEC_DP: ptr--; break;
|
case DEC_DP: ptr--; break;
|
||||||
case OP_INC_VAL: data[ptr]++; break;
|
case INC_VAL: data[ptr]++; break;
|
||||||
case OP_DEC_VAL: data[ptr]--; break;
|
case DEC_VAL: data[ptr]--; break;
|
||||||
case OP_OUT: putchar((signed int)data[ptr]); break;
|
case OUT: putchar((signed int)data[ptr]); break;
|
||||||
case OP_IN: data[ptr] = (unsigned int)getchar(); break;
|
case IN: data[ptr] = (unsigned int)getchar(); break;
|
||||||
case OP_JMP_FWD: if(!data[ptr]) { pc = program[pc].operand; } break;
|
case JMP_FWD: if(!data[ptr]) { pc = program[pc].operand; } break;
|
||||||
case OP_JMP_BCK: if(data[ptr]) { pc = program[pc].operand; } break;
|
case JMP_BCK: if(data[ptr]) { pc = program[pc].operand; } break;
|
||||||
default: die(2, "Unknown instruction.");
|
default: die(127, "nbfi:execute: Unknown instruction.\n");
|
||||||
}
|
}
|
||||||
pc++;
|
pc++;
|
||||||
}
|
}
|
||||||
if(ptr == DATA_SIZE)
|
if(ptr == DATA_SIZE)
|
||||||
die(1, "Program used up too much memory.");
|
die(127, "nbfi:execute: Program used up too much memory.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, const char * argv[]){
|
int main(int argc, const char * argv[]){
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
if(argc != 2)
|
if(argc != 2)
|
||||||
die(1, "Wrong number of arguments supplied.\n");
|
die(127, "nbfi:parse: Wrong number of arguments supplied.\n");
|
||||||
if(!(fp = fopen(argv[1], "r")))
|
if(!(fp = fopen(argv[1], "r")))
|
||||||
die(1, "File could not be opened.\n");
|
die(1, "nbfi:parse: File could not be opened.\n");
|
||||||
compile(fp);
|
compile(fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
execute();
|
execute();
|
||||||
|
Reference in New Issue
Block a user