commit 1b3b1bab8d6bade72495fad32c8a8b17f1e9d92f Author: Veit Heller Date: Fri Jul 25 02:41:51 2014 +0200 initial commit diff --git a/nbfi/helloworld.bf b/nbfi/helloworld.bf new file mode 100644 index 0000000..f079b46 --- /dev/null +++ b/nbfi/helloworld.bf @@ -0,0 +1,42 @@ +++++++++++ +[ + > + +++++++ + > + ++++++++++ + > + +++ + > + + + <<<< + - +] +> +++ +. +> ++ +. ++++++++ +.. ++++ +. +> +++ +. +<< ++++++++++++++++ +. +> +. ++++ +. +------ +. +-------- +. +> ++ +. +> +. diff --git a/nbfi/hw.bf b/nbfi/hw.bf new file mode 100644 index 0000000..265e751 --- /dev/null +++ b/nbfi/hw.bf @@ -0,0 +1 @@ +++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. diff --git a/nbfi/main.c b/nbfi/main.c new file mode 100644 index 0000000..fc073e0 --- /dev/null +++ b/nbfi/main.c @@ -0,0 +1,6 @@ +#include + +int main(){ + printf("Hello, world!\n"); + return 0; +} diff --git a/nbfi/nbfi b/nbfi/nbfi new file mode 100755 index 0000000..86346af Binary files /dev/null and b/nbfi/nbfi differ diff --git a/nbfi/nbfi.c b/nbfi/nbfi.c new file mode 100644 index 0000000..9ec8aee --- /dev/null +++ b/nbfi/nbfi.c @@ -0,0 +1,107 @@ +#include +#include + +#define OP_END 0 +#define OP_INC_DP 1 +#define OP_DEC_DP 2 +#define OP_INC_VAL 3 +#define OP_DEC_VAL 4 +#define OP_OUT 5 +#define OP_IN 6 +#define OP_JMP_FWD 7 +#define OP_JMP_BCK 8 + +#define PROGRAM_SIZE 1048576 +#define MAX_SIZE 5024291 +#define DATA_SIZE 1638375 + +#define STACK_PUSH(A) (stack[sp++] = A) +#define STACK_POP() (stack[--sp]) +#define STACK_EMPTY() (sp == 0) +#define STACK_FULL() (sp == MAX_SIZE) + +static inline void die(int code, char* message){ + fprintf(stderr, message); + exit(code); +} + +struct instruction_t{ + unsigned short operator; + unsigned short operand; +}; + +static struct instruction_t program[PROGRAM_SIZE]; +static unsigned short stack[MAX_SIZE]; +static unsigned int sp = 0; + +void compile(FILE* fp){ + unsigned short pc = 0, jmp_pc; + int ip; + while ((ip = getc(fp)) != EOF && pc < MAX_SIZE){ + switch (ip) { + case '>': program[pc].operator = OP_INC_DP; break; + case '<': program[pc].operator = OP_DEC_DP; break; + case '+': program[pc].operator = OP_INC_VAL; break; + case '-': program[pc].operator = OP_DEC_VAL; break; + case '.': program[pc].operator = OP_OUT; break; + case ',': program[pc].operator = OP_IN; break; + case '[': + program[pc].operator = OP_JMP_FWD; + if (STACK_FULL()) + die(1, "Cannot jump forwards: Stack is full.\n"); + STACK_PUSH(pc); + break; + case ']': + if (STACK_EMPTY()) + die(1, "Cannot jump backwards: Stack is full.\n"); + jmp_pc = STACK_POP(); + program[pc].operator = OP_JMP_BCK; + program[pc].operand = jmp_pc; + program[jmp_pc].operand = pc; + break; + default: + pc--; + break; + } + pc++; + } + if(!STACK_EMPTY()) + die(1, "Program ends with non-empty stack."); + if(pc == MAX_SIZE) + die(1, "Program exceeds maximum program size."); + program[pc].operator = OP_END; +} + +void execute(){ + unsigned short data[DATA_SIZE], pc = 0; + unsigned int ptr = DATA_SIZE; + while (--ptr) data[ptr] = 0; + while (program[pc].operator != OP_END && ptr < DATA_SIZE){ + switch (program[pc].operator){ + case OP_INC_DP: ptr++; break; + case OP_DEC_DP: ptr--; break; + case OP_INC_VAL: data[ptr]++; break; + case OP_DEC_VAL: data[ptr]--; break; + case OP_OUT: putchar(data[ptr]); break; + case OP_IN: data[ptr] = (unsigned int)getchar(); break; + case OP_JMP_FWD: if(!data[ptr]) { pc = program[pc].operand; } break; + case OP_JMP_BCK: if(data[ptr]) { pc = program[pc].operand; } break; + default: die(2, "Unknown instruction."); + } + pc++; + } + if(ptr == DATA_SIZE) + die(1, "Program used up too much memory."); +} + +int main(int argc, const char * argv[]){ + FILE *fp; + if(argc != 2) + die(1, "Wrong number of arguments supplied.\n"); + if(!(fp = fopen(argv[1], "r"))) + die(1, "File could not be opened.\n"); + compile(fp); + fclose(fp); + execute(); + return 0; +} diff --git a/vvm/Makefile b/vvm/Makefile new file mode 100644 index 0000000..ff3b524 --- /dev/null +++ b/vvm/Makefile @@ -0,0 +1,35 @@ +override CFLAGS+=-Werror -Wall -g -fPIC -O2 -DNDEBUG -std=c99 -ftrapv -Wfloat-equal -Wundef -Wwrite-strings -Wconversion -Wuninitialized +PREFIX=/usr/bin +BUILDDIR=bin/ +CC=gcc-mp-4.9 + +TARGET=vvm +SOURCES=$(wildcard src/*.c) + +#Makes everything +all: + mkdir $(BUILDDIR) 2> /dev/null || true + $(CC) $(CFLAGS) $(SOURCES) -o $(BUILDDIR)$(TARGET) + +#Uses picky extensions and makes everything(Extensions may break compiling) +dev: + make all CFLAGS+=-Wshadow -Wunreachable-code -Wswitch-enum -Wswitch-default -Wcast-align -Winit-self -Wpointer-arith -Weffc++ + +#Cleans directory(no uninstall!) +clean: + rm -rf bin + +#Installs into specified(or default) directory +install: + install -d $(PREFIX)/VVM + install $(BUILDDIR)$(TARGET) $(PREFIX)/VVM + +#Uninstalls from specified(or default)directory +uninstall: + rm -rf $(PREFIX)/VVM + +#Checks for bad functions +BADFUNCS='[^_.>a-zA-Z0-9](str(n?cpy|n?cat|xfrm|n?dup|str|pbrk|tok|_)|stpn?cpy|a?sn?printf|byte_)' +check: + @echo Files with potentially dangerous functions: + @grep $(BADFUNCS) $(SOURCES) || echo None diff --git a/vvm/bin/vvm b/vvm/bin/vvm new file mode 100755 index 0000000..4ddd801 Binary files /dev/null and b/vvm/bin/vvm differ diff --git a/vvm/src/main.c b/vvm/src/main.c new file mode 100644 index 0000000..3c001e7 --- /dev/null +++ b/vvm/src/main.c @@ -0,0 +1,34 @@ +#include "vm.h" + +int factorial[] = { + LOAD, -3, + ICONST, 2, + ILT, + BRF, 10, + ICONST, 1, + RET, + LOAD, -3, + LOAD, -3, + ICONST, 1, + ISUB, + CALL, 0, 1, + IMULT, + RET, + ICONST, 12, + CALL, 0, 1, + IPRINT, + HALT +}; + + +int main(){ + int code[] = { ICONST, 72, PRINT, ICONST, 101, PRINT, ICONST, 108, + PRINT, ICONST, 108, PRINT, ICONST, 111, PRINT, ICONST, 44, PRINT, + ICONST, 32, PRINT, ICONST, 119, PRINT, ICONST, 111, PRINT, + ICONST, 114, PRINT, ICONST, 108, PRINT, ICONST, 100, PRINT, + ICONST, 33, GSTORE, 0, GLOAD, 0, PRINT, ICONST, 10, PRINT, HALT }; + vm_execute(factorial, 22, 0, sizeof(factorial) / sizeof(factorial[0])); + printf("\n"); + vm_execute(code, 0, 1, sizeof(code) / sizeof(code[0])); + return 0; +} diff --git a/vvm/src/opcode.c b/vvm/src/opcode.c new file mode 100644 index 0000000..2673427 --- /dev/null +++ b/vvm/src/opcode.c @@ -0,0 +1,23 @@ +#include + +#include "opcode.h" + +const char* opcodes[] = {"IADD", "ISUB", "IMULT", "IDIV", "IMOD", + "ILT", "IEQ", "IGT", "BR", "BRT", "BRF", "ICONST", "LOAD", "GLOAD", + "STORE", "GSTORE", "PRINT", "POP", "HALT", "LEQ", "GEQ", "CALL", "RET", + "IPRINT", "FETCH"}; + +int nargs[] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 0, 2, 0, 0, 0 }; + +instruction* setup_instructions(){ + int i; + static instruction ins[FETCH+1]; + ins[0].operands = 0; + ins[0].name = NULL; + for(i = 1; i <= FETCH; i++){ + ins[i].operands = nargs[i-1]; + ins[i].name = opcodes[i-1]; + } + return ins; +} diff --git a/vvm/src/opcode.h b/vvm/src/opcode.h new file mode 100644 index 0000000..85cb319 --- /dev/null +++ b/vvm/src/opcode.h @@ -0,0 +1,36 @@ +#ifndef OPCODE_H +#define OPCODE_H +#define IADD 1 +#define ISUB 2 +#define IMULT 3 +#define IDIV 4 +#define IMOD 5 +#define ILT 6 +#define IEQ 7 +#define IGT 8 +#define BR 9 +#define BRT 10 +#define BRF 11 +#define ICONST 12 +#define LOAD 13 +#define GLOAD 14 +#define STORE 15 +#define GSTORE 16 +#define PRINT 17 +#define POP 18 +#define HALT 19 +#define LEQ 20 +#define GEQ 21 +#define CALL 22 +#define RET 23 +#define IPRINT 24 +#define FETCH 25 + +typedef struct{ + int operands; + const char* name; +}instruction; + +instruction* setup_instructions(); + +#endif diff --git a/vvm/src/util.h b/vvm/src/util.h new file mode 100644 index 0000000..e46d3bf --- /dev/null +++ b/vvm/src/util.h @@ -0,0 +1,12 @@ +#ifndef UTIL_H +#define UTIL_H +#include +#include + +#define LENGTH(x) (sizeof(x) / sizeof(x[0])) + +static inline void die(int code, const char* message){ + fprintf(stderr, "%s", message); + exit(code); +} +#endif diff --git a/vvm/src/vm.c b/vvm/src/vm.c new file mode 100644 index 0000000..7211b98 --- /dev/null +++ b/vvm/src/vm.c @@ -0,0 +1,149 @@ +#include "vm.h" + +#define MAX_SIZE 4096 +#define TRUE 1 +#define FALSE 0 +#define DEBUG FALSE + +static inline void disassemble(int sp, int fp, int ip, int opcode, instruction* ins, int code[], int stack[]){ + if(opcode > 0 && opcode < 24) + printf("%04d: %s(%d)\n", ip, ins[opcode].name, opcode); + if(ins[opcode].operands == 1) + printf("\t%d\n", code[ip+1]); + else if(ins[opcode].operands == 2) + printf("\t%d, %d\n", code[ip+1], code[ip+2]); + int i; + printf("\n===Stack trace===\n"); + for(i = sp; i >= 0; i--) + printf("%04d: %d\n", i, stack[i]); + printf("\n"); +} + +void vm_execute(int code[], int ip, int datasize, int length){ + int data[datasize]; + int stack[MAX_SIZE]; + int sp = -1; + int fp = -1; + int nargs, addr, a, b; + instruction* ins = setup_instructions(); + while(ip < length){ + int opcode = code[ip]; + ip++; + if(DEBUG){ + if(ip+2 != length) + disassemble(sp, fp, ip, opcode, ins, code, stack); + } + switch(opcode){ + case LOAD: + stack[++sp] = stack[code[ip++]+fp]; + break; + case STORE: + stack[fp+code[ip++]] = stack[sp--]; + case BR: + ip = code[ip]; + break; + case BRT: + addr = code[ip++]; + if(stack[sp--] == TRUE) ip = addr; + break; + case BRF: + addr = code[ip++]; + if(stack[sp--] == FALSE) ip = addr; + break; + case IADD: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a + b; + break; + case ISUB: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a - b; + break; + case IMULT: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a * b; + break; + case IDIV: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a / b; + break; + case IMOD: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a % b; + break; + case ILT: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a < b ? TRUE : FALSE; + break; + case IEQ: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a == b; + break; + case IGT: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a > b ? TRUE : FALSE; + break; + case LEQ: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a <= b ? TRUE : FALSE; + break; + case GEQ: + b = stack[sp--]; + a = stack[sp--]; + stack[++sp] = a >= b ? TRUE : FALSE; + break; + case ICONST: + stack[++sp] = code[ip++]; + break; + case GLOAD: + stack[++sp] = data[code[ip++]]; + break; + case GSTORE: + data[code[ip++]] = stack[sp--]; + break; + case IPRINT: + printf("%d", stack[sp--]); + break; + case PRINT: + putchar(stack[sp--]); + break; + case FETCH: + stack[++sp] = getchar(); + break; + case HALT: + return; + case CALL: + addr = code[ip++]; + nargs = code[ip++]; + stack[++sp] = nargs; + stack[++sp] = fp; + stack[++sp] = ip; + fp = sp; + ip = addr; + break; + case RET: + addr = stack[sp--]; + sp = fp; + ip = stack[sp--]; + fp = stack[sp--]; + nargs = stack[sp--]; + sp -= nargs; + stack[++sp] = addr; + break; + case POP: + sp--; + default: + fprintf(stderr, "Unrecognized: %d\n", opcode); + die(1, "Exit on program failure."); + } + } + return; +} diff --git a/vvm/src/vm.h b/vvm/src/vm.h new file mode 100644 index 0000000..8a56428 --- /dev/null +++ b/vvm/src/vm.h @@ -0,0 +1,10 @@ +#ifndef VM_H +#define VM_H + +#include + +#include "util.h" +#include "opcode.h" + +void vm_execute(int[], int, int, int); +#endif