initial commit
This commit is contained in:
42
nbfi/helloworld.bf
Normal file
42
nbfi/helloworld.bf
Normal file
@@ -0,0 +1,42 @@
|
||||
++++++++++
|
||||
[
|
||||
>
|
||||
+++++++
|
||||
>
|
||||
++++++++++
|
||||
>
|
||||
+++
|
||||
>
|
||||
+
|
||||
<<<<
|
||||
-
|
||||
]
|
||||
>
|
||||
++
|
||||
.
|
||||
>
|
||||
+
|
||||
.
|
||||
+++++++
|
||||
..
|
||||
+++
|
||||
.
|
||||
>
|
||||
++
|
||||
.
|
||||
<<
|
||||
+++++++++++++++
|
||||
.
|
||||
>
|
||||
.
|
||||
+++
|
||||
.
|
||||
------
|
||||
.
|
||||
--------
|
||||
.
|
||||
>
|
||||
+
|
||||
.
|
||||
>
|
||||
.
|
1
nbfi/hw.bf
Normal file
1
nbfi/hw.bf
Normal file
@@ -0,0 +1 @@
|
||||
++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
|
6
nbfi/main.c
Normal file
6
nbfi/main.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(){
|
||||
printf("Hello, world!\n");
|
||||
return 0;
|
||||
}
|
107
nbfi/nbfi.c
Normal file
107
nbfi/nbfi.c
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
35
vvm/Makefile
Normal file
35
vvm/Makefile
Normal file
@@ -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
|
BIN
vvm/bin/vvm
Executable file
BIN
vvm/bin/vvm
Executable file
Binary file not shown.
34
vvm/src/main.c
Normal file
34
vvm/src/main.c
Normal file
@@ -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;
|
||||
}
|
23
vvm/src/opcode.c
Normal file
23
vvm/src/opcode.c
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
36
vvm/src/opcode.h
Normal file
36
vvm/src/opcode.h
Normal file
@@ -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
|
12
vvm/src/util.h
Normal file
12
vvm/src/util.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define LENGTH(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
static inline void die(int code, const char* message){
|
||||
fprintf(stderr, "%s", message);
|
||||
exit(code);
|
||||
}
|
||||
#endif
|
149
vvm/src/vm.c
Normal file
149
vvm/src/vm.c
Normal file
@@ -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;
|
||||
}
|
10
vvm/src/vm.h
Normal file
10
vvm/src/vm.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef VM_H
|
||||
#define VM_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "opcode.h"
|
||||
|
||||
void vm_execute(int[], int, int, int);
|
||||
#endif
|
Reference in New Issue
Block a user