This commit is contained in:
hellerve
2015-07-14 18:06:44 +02:00
commit 591a51290c
5 changed files with 181 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
bin/

41
Makefile Normal file
View File

@@ -0,0 +1,41 @@
STD=-std=c11
override CFLAGS+=-Werror -Wall -g -fPIC -O2 -DNDEBUG -ftrapv -Wfloat-equal -Wundef -Wwrite-strings -Wconversion -Wuninitialized -pedantic
PREFIX=/usr/bin/
BUILDDIR=bin/
CC=cc
TARGET=cmm
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 -fsanitize=address $(STD)"
#Runs all tests
runtests:
./test.sh
#Cleans directory(no uninstall!)
clean:
rm -rf bin
#Installs into specified(or default) directory
install:
install -d $(PREFIX)$(TARGET)
install $(BUILDDIR)$(TARGET) $(PREFIX)$(TARGET)
#Uninstalls from specified(or default)directory
uninstall:
rm -rf $(PREFIX)$(TARGET)
#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

22
README.md Normal file
View File

@@ -0,0 +1,22 @@
#cmm
A C implementation of the [Mythical Machine](http://www.openbookproject.net/courses/python4fun/simulator.html)
that executes its' bytecode.
##Building & Installing
The project comes with a Makefile. Just run `make` to get a build in the
`bin` directory. If you really want to install it, run `make install`. That
will only work on Unix systems, though, I am afraid and may clutter your workspace.
##Usage
```
usage: cmm program_name
```
This will "parse" the file and execute the bytecode.
<hr/>
*Have fun!*

4
examples/example.mml Normal file
View File

@@ -0,0 +1,4 @@
100 031012 Load register one with the number 12
101 032013 Load register two with the number 13
102 051002 Add register two to register one.
103 000000 Halt. The answer is in register one.

113
src/cmm.c Normal file
View File

@@ -0,0 +1,113 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
typedef struct program {
int p_reg;
int i_reg;
int mem[1000];
int reg[10];
} program;
program* get_new_program() {
program* ret = calloc(1, sizeof(ret));
return ret;
}
static inline void print_usage(char* name, uint8_t code) {
printf("usage: %s program_name\n", name);
exit(code);
}
static inline void unparseable() {
puts("the program is unparseable!");
exit(127);
}
int execute(program* ex) {
int opcode, r, addr;
ex->i_reg = ex->mem[ex->p_reg++];
opcode = ex->i_reg / 10000;
r = (ex->i_reg / 1000) % 10;
addr = ex->i_reg % 1000;
switch(opcode) {
case 0: return 0;
break;
case 1: ex->reg[r] = ex->mem[addr];
break;
case 2: ex->mem[addr] = ex->reg[r];
break;
case 3: ex->reg[r] = addr;
break;
case 4: ex->reg[r] = ex->mem[ex->reg[addr]];
break;
case 5: ex->reg[r] += ex->reg[addr];
break;
case 6: ex->reg[r] -= ex->reg[addr];
break;
case 7: ex->reg[r] *= ex->reg[addr];
break;
case 8: ex->reg[r] /= ex->reg[addr];
break;
case 10: ex->p_reg += addr;
break;
case 11: if (!ex->reg[r]) ex->p_reg = addr;
break;
}
return 1;
}
program* load_program(char* file_name) {
FILE* file = fopen(file_name, "r");
char* line = NULL;
char* token = NULL;
size_t len = 0;
uint8_t count;
ssize_t read;
int address[2];
program* ret = get_new_program();
if(!file) return NULL;
while((read = getline(&line, &len, file)) != -1) {
if(line[0] < '0') continue;
token = strtok(line, " ");
count = 0;
while(token) {
if(count > 1) {
ret->mem[address[0]] = address[1];
break;
}
address[count] = atoi(token);
count++;
token = strtok(NULL, " ");
}
}
return ret;
}
int main(int argc, char** argv) {
if(argc != 2) print_usage(argv[0], 1);
program* gotten = load_program(argv[1]);
if(!gotten) unparseable();
gotten->p_reg = 100;
while(execute(gotten));
return 0;
}