-
Notifications
You must be signed in to change notification settings - Fork 61
/
Copy pathbuzzrun.c
133 lines (130 loc) · 3.99 KB
/
buzzrun.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <buzz/buzzasm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void usage(const char* path, int status) {
fprintf(stderr, "Usage:\n\t%s [--trace] <file.bo> <file.bdb>\n\n", path);
exit(status);
}
int print(buzzvm_t vm) {
for(int i = 1; i < buzzdarray_size(vm->lsyms->syms); ++i) {
buzzvm_lload(vm, i);
buzzobj_t o = buzzvm_stack_at(vm, 1);
buzzvm_pop(vm);
switch(o->o.type) {
case BUZZTYPE_NIL:
fprintf(stdout, "[nil]");
break;
case BUZZTYPE_INT:
fprintf(stdout, "%d", o->i.value);
break;
case BUZZTYPE_FLOAT:
fprintf(stdout, "%f", o->f.value);
break;
case BUZZTYPE_TABLE:
fprintf(stdout, "[table with %d elems]", (buzzdict_size(o->t.value)));
break;
case BUZZTYPE_CLOSURE:
if(o->c.value.isnative)
fprintf(stdout, "[n-closure @%d]", o->c.value.ref);
else
fprintf(stdout, "[c-closure @%d]", o->c.value.ref);
break;
case BUZZTYPE_STRING:
fprintf(stdout, "%s", o->s.value.str);
break;
case BUZZTYPE_USERDATA:
fprintf(stdout, "[userdata @%p]", o->u.value);
break;
default:
break;
}
}
fprintf(stdout, "\n");
return buzzvm_ret0(vm);
}
int main(int argc, char** argv) {
/* The bytecode filename */
char* bcfname;
/* The debugging information file name */
char* dbgfname;
/* Whether or not to show the assembly information */
int trace = 0;
/* Parse command line */
if(argc < 3 || argc > 4) usage(argv[0], 0);
if(argc == 3) {
bcfname = argv[1];
dbgfname = argv[2];
}
else {
bcfname = argv[2];
dbgfname = argv[3];
if(strcmp(argv[1], "--trace") != 0) {
fprintf(stderr, "error: %s: unrecognized option '%s'\n", argv[0], argv[1]);
usage(argv[0], 1);
}
trace = 1;
}
/* Read bytecode and fill in data structure */
FILE* fd = fopen(bcfname, "rb");
if(!fd) perror(bcfname);
fseek(fd, 0, SEEK_END);
size_t bcode_size = ftell(fd);
rewind(fd);
uint8_t* bcode_buf = (uint8_t*)malloc(bcode_size);
if(fread(bcode_buf, 1, bcode_size, fd) < bcode_size) {
perror(bcfname);
}
fclose(fd);
/* Read debug information */
buzzdebug_t dbg_buf = buzzdebug_new();
if(!buzzdebug_fromfile(dbg_buf, dbgfname)) {
perror(dbgfname);
}
/* Create new VM */
buzzvm_t vm = buzzvm_new(1);
/* Set byte code */
buzzvm_set_bcode(vm, bcode_buf, bcode_size);
/* Register hook functions */
buzzvm_pushs(vm, buzzvm_string_register(vm, "log", 1));
buzzvm_pushcc(vm, buzzvm_function_register(vm, print));
buzzvm_gstore(vm);
/* Run byte code */
do if(trace) buzzdebug_stack_dump(vm, 1, stdout);
while(buzzvm_step(vm) == BUZZVM_STATE_READY);
/* Done running, check final state */
int retval;
if(vm->state == BUZZVM_STATE_DONE) {
/* Execution terminated without errors */
if(trace) buzzdebug_stack_dump(vm, 1, stdout);
fprintf(stdout, "%s: execution terminated correctly\n\n",
bcfname);
retval = 0;
}
else {
/* Execution terminated with errors */
if(trace) buzzdebug_stack_dump(vm, 1, stdout);
const buzzdebug_entry_t* dbg = buzzdebug_info_get_fromoffset(dbg_buf, &vm->oldpc);
if(dbg != NULL) {
fprintf(stderr, "%s: execution terminated abnormally at %s:%" PRIu64 ":%" PRIu64 " : %s\n\n",
bcfname,
(*dbg)->fname,
(*dbg)->line,
(*dbg)->col,
vm->errormsg);
}
else {
fprintf(stderr, "%s: execution terminated abnormally at bytecode offset %d: %s\n\n",
bcfname,
vm->oldpc,
vm->errormsg);
}
retval = 1;
}
/* Destroy VM */
free(bcode_buf);
buzzdebug_destroy(&dbg_buf);
buzzvm_destroy(&vm);
/* All done */
return retval;
}