diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/compile.c | 205 | ||||
| -rw-r--r-- | src/ducky.h | 10 | ||||
| -rw-r--r-- | src/emitc.c | 79 | ||||
| -rw-r--r-- | src/interp.c | 417 | ||||
| -rw-r--r-- | src/vm.c | 159 |
5 files changed, 452 insertions, 418 deletions
diff --git a/src/compile.c b/src/compile.c index 58abdeb..29cb91d 100644 --- a/src/compile.c +++ b/src/compile.c @@ -35,6 +35,8 @@ static unsigned lines_executed = 0, current_line = 0, num_lines; static int file_des = -1, out_fd = -1; +static jmp_buf exit_point; + struct var_t { char name[VARNAME_MAX]; bool constant; @@ -169,10 +171,10 @@ static void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, vsnprintf(fmtbuf, sizeof(fmtbuf), fmt, ap); if(current_line) vid_logf("Line %d: ", current_line); - vid_logf("ERROR: %s\n", fmtbuf); + vid_logf("ERROR: %s", fmtbuf); va_end(ap); - exit(EXIT_FAILURE); + longjmp(exit_point, 1); } static void __attribute__((format(printf,1,2))) warning(const char *fmt, ...) @@ -1616,128 +1618,133 @@ static void init_globals(void) bytes_written = 0; } -void ducky_compile(int fd, bool verbose, int out) +int ducky_compile(int fd, bool verbose, int out) { - init_globals(); - - if(verbose) + if(!setjmp(exit_point)) { - vid_logf("COMPILER INIT"); - } + init_globals(); - file_des = fd; - out_fd = out; + if(verbose) + { + vid_logf("COMPILER INIT"); + } - atexit(exit_handler); + file_des = fd; + out_fd = out; - if(file_des < 0) - error("invalid file"); + atexit(exit_handler); - init_optable(); - init_tokmap(); + if(file_des < 0) + error("invalid file"); - line_offset = index_lines(file_des, &num_lines); - write_imm(DUCKY_MAGIC); - write_imm(num_lines); - off_t linetab_off = bytes_written; - for(unsigned i = 1; i <= num_lines; ++i) - { - write_imm(0); - } - if(verbose) - { - vid_logf("Indexing complete (%u lines).", num_lines); - vid_logf("Compiling..."); - } + init_optable(); + init_tokmap(); + + line_offset = index_lines(file_des, &num_lines); + write_imm(DUCKY_MAGIC); + write_imm(num_lines); + off_t linetab_off = bytes_written; + for(unsigned i = 1; i <= num_lines; ++i) + { + write_imm(0); + } + if(verbose) + { + vid_logf("Indexing complete (%u lines).", num_lines); + vid_logf("Compiling..."); + } - /* initialize some other constants */ + /* initialize some other constants */ - makeConstantVariable(".", 0); + makeConstantVariable(".", 0); - makeConstantVariable("true", 1); - makeConstantVariable("false", 0); + makeConstantVariable("true", 1); + makeConstantVariable("false", 0); - /* initialize labels (using output from index_lines) */ - index_labels(file_des); + /* initialize labels (using output from index_lines) */ + index_labels(file_des); - int repeats_left = 0; - off_t code_start = bytes_written; + int repeats_left = 0; + off_t code_start = bytes_written; - while(1) - { - char instr_buf[MAX_LINE_LEN]; - memset(instr_buf, 0, sizeof(instr_buf)); - if(read_line(file_des, instr_buf, sizeof(instr_buf)) <= 0) + while(1) { - if(verbose) - vid_logf("end of file"); - goto done; - } - char *tok = NULL, *save = NULL; + char instr_buf[MAX_LINE_LEN]; + memset(instr_buf, 0, sizeof(instr_buf)); + if(read_line(file_des, instr_buf, sizeof(instr_buf)) <= 0) + { + if(verbose) + vid_logf("end of file"); + goto done; + } + char *tok = NULL, *save = NULL; - ++current_line; - write_instr(LINEMARK); + ++current_line; + write_instr(LINEMARK); - char *buf = instr_buf; + char *buf = instr_buf; - line_offset[current_line] = bytes_written; + line_offset[current_line] = bytes_written; - /* compile all the commands on this line/instruction */ - do { - tok = strtok_r(buf, " -\t", &save); - buf = NULL; + /* compile all the commands on this line/instruction */ + do { + tok = strtok_r(buf, " -\t", &save); + buf = NULL; - if(!tok) - break; + if(!tok) + break; - int hash = tok_hash(tok) % TOKMAP_SIZE; - struct token_t *t = tokmap+hash; - if(hash >= 0 && strcmp(t->tok, tok) == 0) - switch(tokmap[hash].func(&save)) + int hash = tok_hash(tok) % TOKMAP_SIZE; + struct token_t *t = tokmap+hash; + if(hash >= 0 && strcmp(t->tok, tok) == 0) + switch(tokmap[hash].func(&save)) + { + case OK: + break; + case BREAK: + goto break_out; + case DONE: + goto done; + case NEXT: + goto next_line; + default: + error("FIXME: invalid return value"); + } +#ifdef DUCKY_ROCKBOX + else if(strlen(tok) == 1) { - case OK: - break; - case BREAK: - goto break_out; - case DONE: - goto done; - case NEXT: - goto next_line; - default: - error("FIXME: invalid return value"); + write_instr(ADD_CHAR); + write_byte(tok[0]); } -#ifdef DUCKY_ROCKBOX - else if(strlen(tok) == 1) - { - write_instr(ADD_CHAR); - write_byte(tok[0]); - } #endif - else if(tok[0] == '#') - goto next_line; - else - { - error("unknown token `%s` on line %d %d", tok, current_line); - goto done; - } - } while(tok); - break_out: - ; - next_line: - ; - } + else if(tok[0] == '#') + goto next_line; + else + { + error("unknown token `%s` on line %d %d", tok, current_line); + goto done; + } + } while(tok); + break_out: + ; + next_line: + ; + } -done: + done: - /* add a final instruction to flush the key buffer */ - write_instr(LINEMARK); + /* add a final instruction to flush the key buffer */ + write_instr(LINEMARK); - /* go back and fill in the offset table */ - lseek(out_fd, linetab_off, SEEK_SET); - for(unsigned i = 1; i <= num_lines; ++i) - { - write_imm(line_offset[i]); - } + /* go back and fill in the offset table */ + lseek(out_fd, linetab_off, SEEK_SET); + for(unsigned i = 1; i <= num_lines; ++i) + { + write_imm(line_offset[i]); + } - return; + return 0; + } + else + return 1; } diff --git a/src/ducky.h b/src/ducky.h index d1f7dc7..1552134 100644 --- a/src/ducky.h +++ b/src/ducky.h @@ -13,10 +13,12 @@ #define MIN(x,y) ((x<y)?(x):(y)) -void ducky_main(int fd, bool verbose); -void ducky_compile(int fd, bool verbose, int out_fd); -void ducky_vm(int fd); -void ducky_to_c(int fd, int out_fd); +#define OK 0 + +int ducky_interp(int fd, bool verbose); +int ducky_compile(int fd, bool verbose, int out_fd); +int ducky_vm(int fd); +int ducky_to_c(int fd, int out_fd); typedef int32_t imm_t; typedef uint8_t instr_t; diff --git a/src/emitc.c b/src/emitc.c index bf79a47..e200ce5 100644 --- a/src/emitc.c +++ b/src/emitc.c @@ -13,14 +13,15 @@ struct var_t { bool constant; }; -int file_des, out_fd; -unsigned current_line, num_lines; +static int file_des, out_fd; +static unsigned current_line, num_lines; -off_t *line_offset; +static off_t *line_offset; -bool want_quit; -int repeats_left; -imm_t repeat_line; +static bool want_quit; +static int repeats_left; +static imm_t repeat_line; +static jmp_buf exit_point; static void error(const char *fmt, ...) __attribute__((noreturn,format(print,1,2))); static void vid_write(const char *str); @@ -138,7 +139,7 @@ static void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, vid_writef("ERROR: %s\n", fmtbuf); va_end(ap); - exit(EXIT_FAILURE); + longjmp(exit_point, 1); } static void __attribute__((format(printf,1,2))) warning(const char *fmt, ...) @@ -762,22 +763,8 @@ static void (*instr_tab[0x100])(void) = { inc_line_pointer, /* 0xff */ }; -void ducky_to_c(int fd, int out) +void write_stub_code(int num_lines) { - file_des = fd; - out_fd = out; - - init_globals(); - - if(read_imm() != DUCKY_MAGIC) - error("unknown format"); - - num_lines = read_imm(); - for(unsigned int i = 1; i <= num_lines; ++i) - { - read_imm(); - } - write_src("/* generated by ducky */\n\n"); write_src("#include <stdarg.h>\n"); @@ -875,7 +862,6 @@ void ducky_to_c(int fd, int out) write_src("{\n"); write_src("/* this uses labels as values, a GCC extension */\n"); - write_src("const void *jump_table[%d] = ", num_lines + 1); write_src("{\n"); write_src("NULL,\n"); @@ -885,18 +871,43 @@ void ducky_to_c(int fd, int out) } write_src("};\n"); write_src_noindent("\n"); +} - /* and... compile! */ - while(!want_quit) +int ducky_to_c(int fd, int out) +{ + if(!setjmp(exit_point)) { - instr_t instr = read_instr(); - if(want_quit) - break; - void (*handler)(void) = instr_tab[instr]; - if(handler) - handler(); - else - error("invalid instruction %d", instr); + file_des = fd; + out_fd = out; + + init_globals(); + + if(read_imm() != DUCKY_MAGIC) + error("unknown format"); + + num_lines = read_imm(); + for(unsigned int i = 1; i <= num_lines; ++i) + { + read_imm(); + } + + write_stub_code(num_lines); + + /* and... compile! */ + while(!want_quit) + { + instr_t instr = read_instr(); + if(want_quit) + break; + void (*handler)(void) = instr_tab[instr]; + if(handler) + handler(); + else + error("invalid instruction %d", instr); + } + write_src("}\n"); + return 0; } - write_src("}\n"); + else + return 1; } diff --git a/src/interp.c b/src/interp.c index 8a2b91a..d5d567f 100644 --- a/src/interp.c +++ b/src/interp.c @@ -53,6 +53,8 @@ static unsigned stack_frame = 0; static int file_des = -1; +static jmp_buf exit_point; + struct varnode_t { char name[VARNAME_MAX + 1]; vartype val; @@ -202,7 +204,7 @@ static void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, vid_writef("ERROR: %s\n", fmtbuf); va_end(ap); - exit(EXIT_FAILURE); + longjmp(exit_point, 1); } static void __attribute__((format(printf,1,2))) warning(const char *fmt, ...) @@ -1065,111 +1067,111 @@ static struct token_t tokmap[TOKMAP_SIZE]; */ static int g[] = { - 19, 12, -1, 15, 17, 1, 4, 4, 0, 13, - 10, 19, 18, -1, 14, 19, 19, 21, 19, 0, - 7, 0, 15, 18, 4, 0, 4, 3, + 19, 12, -1, 15, 17, 1, 4, 4, 0, 13, + 10, 19, 18, -1, 14, 19, 19, 21, 19, 0, + 7, 0, 15, 18, 4, 0, 4, 3, }; static int T0[] = { - 0x15, 0x0c, 0x1a, 0x17, 0x16, 0x02, 0x16, 0x07, 0x17, 0x09, - 0x0f, 0x0f, 0x0f, 0x17, 0x07, 0x0c, 0x1a, 0x08, 0x17, 0x04, - 0x14, 0x07, 0x06, 0x07, 0x10, 0x0e, 0x0e, 0x18, 0x01, 0x08, - 0x1b, 0x17, 0x14, 0x19, 0x12, 0x1a, 0x0b, 0x0c, 0x12, 0x07, - 0x05, 0x05, 0x06, 0x13, 0x06, 0x19, 0x07, 0x0d, 0x01, 0x0c, - 0x1a, 0x09, 0x15, 0x1b, 0x16, 0x03, 0x15, 0x19, 0x12, 0x07, - 0x1b, 0x05, 0x08, 0x0a, 0x15, 0x05, 0x16, 0x0b, 0x0a, 0x00, - 0x0e, 0x0d, 0x08, 0x0a, 0x04, 0x1b, 0x07, 0x17, 0x0c, 0x15, - 0x07, 0x0a, 0x02, 0x0c, 0x15, 0x08, 0x0d, 0x12, 0x10, 0x00, - 0x07, 0x13, 0x15, 0x10, 0x17, 0x0a, 0x0e, 0x01, 0x14, 0x14, - 0x1a, 0x06, 0x15, 0x05, 0x0a, 0x14, 0x03, 0x12, 0x04, 0x0c, - 0x11, 0x1b, 0x0e, 0x1b, 0x17, 0x03, 0x08, 0x09, 0x15, 0x08, - 0x15, 0x0c, 0x1b, 0x0e, 0x00, 0x16, 0x08, 0x1b, 0x08, 0x10, - 0x0a, 0x00, 0x09, 0x01, 0x00, 0x09, 0x13, 0x03, 0x19, 0x03, - 0x05, 0x15, 0x10, 0x06, 0x13, 0x02, 0x19, 0x15, 0x13, 0x12, - 0x18, 0x16, 0x02, 0x0b, 0x0a, 0x1b, 0x0a, 0x15, 0x08, 0x06, - 0x09, 0x12, 0x06, 0x12, 0x14, 0x12, 0x0c, 0x17, 0x15, 0x09, - 0x1a, 0x0b, 0x05, 0x00, 0x1b, 0x0c, 0x10, 0x09, 0x02, 0x17, - 0x11, 0x0a, 0x15, 0x11, 0x18, 0x12, 0x16, 0x00, 0x0e, 0x10, - 0x18, 0x11, 0x0b, 0x07, 0x0b, 0x1a, 0x1b, 0x07, 0x07, 0x15, - 0x0a, 0x16, 0x1a, 0x0f, 0x06, 0x19, 0x0c, 0x17, 0x06, 0x0e, - 0x12, 0x08, 0x18, 0x17, 0x09, 0x0c, 0x03, 0x1b, 0x15, 0x0e, - 0x06, 0x01, 0x11, 0x0e, 0x04, 0x08, 0x05, 0x1b, 0x05, 0x03, - 0x15, 0x04, 0x17, 0x10, 0x0e, 0x07, 0x0e, 0x14, 0x13, 0x17, - 0x14, 0x1b, 0x0a, 0x07, 0x18, 0x04, 0x03, 0x00, 0x10, 0x19, - 0x1a, 0x16, 0x0a, 0x0f, 0x14, 0x1a, 0x18, 0x19, 0x0c, 0x1b, - 0x06, 0x0a, 0x03, 0x0b, 0x0e, 0x1b, 0x1b, 0x0d, 0x03, 0x0d, - 0x19, 0x0a, 0x0f, 0x14, 0x14, 0x06, 0x00, 0x01, 0x10, 0x0d, - 0x19, 0x18, 0x09, 0x1b, 0x17, 0x16, 0x14, 0x15, 0x0b, 0x10, - 0x14, 0x02, 0x1b, 0x08, 0x0d, 0x0d, 0x13, 0x0c, 0x0a, 0x16, - 0x09, + 0x15, 0x0c, 0x1a, 0x17, 0x16, 0x02, 0x16, 0x07, 0x17, 0x09, + 0x0f, 0x0f, 0x0f, 0x17, 0x07, 0x0c, 0x1a, 0x08, 0x17, 0x04, + 0x14, 0x07, 0x06, 0x07, 0x10, 0x0e, 0x0e, 0x18, 0x01, 0x08, + 0x1b, 0x17, 0x14, 0x19, 0x12, 0x1a, 0x0b, 0x0c, 0x12, 0x07, + 0x05, 0x05, 0x06, 0x13, 0x06, 0x19, 0x07, 0x0d, 0x01, 0x0c, + 0x1a, 0x09, 0x15, 0x1b, 0x16, 0x03, 0x15, 0x19, 0x12, 0x07, + 0x1b, 0x05, 0x08, 0x0a, 0x15, 0x05, 0x16, 0x0b, 0x0a, 0x00, + 0x0e, 0x0d, 0x08, 0x0a, 0x04, 0x1b, 0x07, 0x17, 0x0c, 0x15, + 0x07, 0x0a, 0x02, 0x0c, 0x15, 0x08, 0x0d, 0x12, 0x10, 0x00, + 0x07, 0x13, 0x15, 0x10, 0x17, 0x0a, 0x0e, 0x01, 0x14, 0x14, + 0x1a, 0x06, 0x15, 0x05, 0x0a, 0x14, 0x03, 0x12, 0x04, 0x0c, + 0x11, 0x1b, 0x0e, 0x1b, 0x17, 0x03, 0x08, 0x09, 0x15, 0x08, + 0x15, 0x0c, 0x1b, 0x0e, 0x00, 0x16, 0x08, 0x1b, 0x08, 0x10, + 0x0a, 0x00, 0x09, 0x01, 0x00, 0x09, 0x13, 0x03, 0x19, 0x03, + 0x05, 0x15, 0x10, 0x06, 0x13, 0x02, 0x19, 0x15, 0x13, 0x12, + 0x18, 0x16, 0x02, 0x0b, 0x0a, 0x1b, 0x0a, 0x15, 0x08, 0x06, + 0x09, 0x12, 0x06, 0x12, 0x14, 0x12, 0x0c, 0x17, 0x15, 0x09, + 0x1a, 0x0b, 0x05, 0x00, 0x1b, 0x0c, 0x10, 0x09, 0x02, 0x17, + 0x11, 0x0a, 0x15, 0x11, 0x18, 0x12, 0x16, 0x00, 0x0e, 0x10, + 0x18, 0x11, 0x0b, 0x07, 0x0b, 0x1a, 0x1b, 0x07, 0x07, 0x15, + 0x0a, 0x16, 0x1a, 0x0f, 0x06, 0x19, 0x0c, 0x17, 0x06, 0x0e, + 0x12, 0x08, 0x18, 0x17, 0x09, 0x0c, 0x03, 0x1b, 0x15, 0x0e, + 0x06, 0x01, 0x11, 0x0e, 0x04, 0x08, 0x05, 0x1b, 0x05, 0x03, + 0x15, 0x04, 0x17, 0x10, 0x0e, 0x07, 0x0e, 0x14, 0x13, 0x17, + 0x14, 0x1b, 0x0a, 0x07, 0x18, 0x04, 0x03, 0x00, 0x10, 0x19, + 0x1a, 0x16, 0x0a, 0x0f, 0x14, 0x1a, 0x18, 0x19, 0x0c, 0x1b, + 0x06, 0x0a, 0x03, 0x0b, 0x0e, 0x1b, 0x1b, 0x0d, 0x03, 0x0d, + 0x19, 0x0a, 0x0f, 0x14, 0x14, 0x06, 0x00, 0x01, 0x10, 0x0d, + 0x19, 0x18, 0x09, 0x1b, 0x17, 0x16, 0x14, 0x15, 0x0b, 0x10, + 0x14, 0x02, 0x1b, 0x08, 0x0d, 0x0d, 0x13, 0x0c, 0x0a, 0x16, + 0x09, }; static int T1[] = { - 0x13, 0x0e, 0x17, 0x12, 0x13, 0x12, 0x08, 0x19, 0x05, 0x0d, - 0x0b, 0x07, 0x06, 0x05, 0x0b, 0x0f, 0x06, 0x07, 0x12, 0x06, - 0x11, 0x0d, 0x08, 0x10, 0x18, 0x1b, 0x18, 0x12, 0x03, 0x00, - 0x00, 0x16, 0x1a, 0x07, 0x18, 0x11, 0x19, 0x10, 0x1a, 0x0e, - 0x0e, 0x16, 0x16, 0x02, 0x10, 0x0d, 0x11, 0x0a, 0x02, 0x14, - 0x00, 0x0c, 0x1a, 0x1a, 0x08, 0x02, 0x01, 0x06, 0x0b, 0x0b, - 0x06, 0x02, 0x13, 0x15, 0x0f, 0x11, 0x0d, 0x01, 0x04, 0x0c, - 0x0b, 0x13, 0x02, 0x11, 0x06, 0x12, 0x0e, 0x07, 0x01, 0x10, - 0x1b, 0x01, 0x01, 0x0a, 0x0b, 0x09, 0x0c, 0x13, 0x11, 0x0a, - 0x03, 0x11, 0x02, 0x13, 0x01, 0x08, 0x0c, 0x0a, 0x06, 0x0e, - 0x00, 0x13, 0x1b, 0x03, 0x12, 0x01, 0x01, 0x0e, 0x0d, 0x09, - 0x11, 0x1b, 0x08, 0x05, 0x0b, 0x0c, 0x02, 0x08, 0x10, 0x13, - 0x02, 0x13, 0x14, 0x04, 0x16, 0x15, 0x18, 0x06, 0x10, 0x13, - 0x1a, 0x01, 0x03, 0x16, 0x17, 0x12, 0x1b, 0x10, 0x0f, 0x0f, - 0x06, 0x0f, 0x0f, 0x1a, 0x10, 0x17, 0x18, 0x09, 0x06, 0x10, - 0x01, 0x03, 0x06, 0x0d, 0x03, 0x0d, 0x0d, 0x0f, 0x16, 0x09, - 0x13, 0x14, 0x0b, 0x16, 0x1a, 0x12, 0x0d, 0x1a, 0x06, 0x00, - 0x19, 0x18, 0x17, 0x18, 0x1b, 0x10, 0x0d, 0x14, 0x17, 0x16, - 0x0a, 0x04, 0x0e, 0x03, 0x10, 0x1a, 0x01, 0x10, 0x19, 0x04, - 0x09, 0x0f, 0x08, 0x0b, 0x1a, 0x0f, 0x0f, 0x09, 0x09, 0x1b, - 0x18, 0x08, 0x16, 0x03, 0x10, 0x05, 0x14, 0x02, 0x19, 0x0f, - 0x18, 0x13, 0x03, 0x16, 0x06, 0x1b, 0x01, 0x0f, 0x19, 0x0d, - 0x00, 0x0a, 0x11, 0x0f, 0x0d, 0x0e, 0x08, 0x10, 0x1b, 0x0c, - 0x1b, 0x19, 0x08, 0x17, 0x0c, 0x1b, 0x0a, 0x12, 0x0d, 0x0f, - 0x0a, 0x14, 0x04, 0x0f, 0x0b, 0x05, 0x0f, 0x18, 0x04, 0x18, - 0x09, 0x05, 0x06, 0x1b, 0x04, 0x13, 0x19, 0x0c, 0x1b, 0x0c, - 0x18, 0x19, 0x08, 0x0e, 0x11, 0x0b, 0x03, 0x16, 0x1b, 0x15, - 0x11, 0x14, 0x09, 0x09, 0x17, 0x0e, 0x12, 0x1a, 0x14, 0x12, - 0x19, 0x08, 0x16, 0x07, 0x12, 0x0a, 0x17, 0x14, 0x13, 0x06, - 0x10, 0x0f, 0x03, 0x18, 0x0d, 0x04, 0x13, 0x10, 0x1b, 0x03, - 0x09, + 0x13, 0x0e, 0x17, 0x12, 0x13, 0x12, 0x08, 0x19, 0x05, 0x0d, + 0x0b, 0x07, 0x06, 0x05, 0x0b, 0x0f, 0x06, 0x07, 0x12, 0x06, + 0x11, 0x0d, 0x08, 0x10, 0x18, 0x1b, 0x18, 0x12, 0x03, 0x00, + 0x00, 0x16, 0x1a, 0x07, 0x18, 0x11, 0x19, 0x10, 0x1a, 0x0e, + 0x0e, 0x16, 0x16, 0x02, 0x10, 0x0d, 0x11, 0x0a, 0x02, 0x14, + 0x00, 0x0c, 0x1a, 0x1a, 0x08, 0x02, 0x01, 0x06, 0x0b, 0x0b, + 0x06, 0x02, 0x13, 0x15, 0x0f, 0x11, 0x0d, 0x01, 0x04, 0x0c, + 0x0b, 0x13, 0x02, 0x11, 0x06, 0x12, 0x0e, 0x07, 0x01, 0x10, + 0x1b, 0x01, 0x01, 0x0a, 0x0b, 0x09, 0x0c, 0x13, 0x11, 0x0a, + 0x03, 0x11, 0x02, 0x13, 0x01, 0x08, 0x0c, 0x0a, 0x06, 0x0e, + 0x00, 0x13, 0x1b, 0x03, 0x12, 0x01, 0x01, 0x0e, 0x0d, 0x09, + 0x11, 0x1b, 0x08, 0x05, 0x0b, 0x0c, 0x02, 0x08, 0x10, 0x13, + 0x02, 0x13, 0x14, 0x04, 0x16, 0x15, 0x18, 0x06, 0x10, 0x13, + 0x1a, 0x01, 0x03, 0x16, 0x17, 0x12, 0x1b, 0x10, 0x0f, 0x0f, + 0x06, 0x0f, 0x0f, 0x1a, 0x10, 0x17, 0x18, 0x09, 0x06, 0x10, + 0x01, 0x03, 0x06, 0x0d, 0x03, 0x0d, 0x0d, 0x0f, 0x16, 0x09, + 0x13, 0x14, 0x0b, 0x16, 0x1a, 0x12, 0x0d, 0x1a, 0x06, 0x00, + 0x19, 0x18, 0x17, 0x18, 0x1b, 0x10, 0x0d, 0x14, 0x17, 0x16, + 0x0a, 0x04, 0x0e, 0x03, 0x10, 0x1a, 0x01, 0x10, 0x19, 0x04, + 0x09, 0x0f, 0x08, 0x0b, 0x1a, 0x0f, 0x0f, 0x09, 0x09, 0x1b, + 0x18, 0x08, 0x16, 0x03, 0x10, 0x05, 0x14, 0x02, 0x19, 0x0f, + 0x18, 0x13, 0x03, 0x16, 0x06, 0x1b, 0x01, 0x0f, 0x19, 0x0d, + 0x00, 0x0a, 0x11, 0x0f, 0x0d, 0x0e, 0x08, 0x10, 0x1b, 0x0c, + 0x1b, 0x19, 0x08, 0x17, 0x0c, 0x1b, 0x0a, 0x12, 0x0d, 0x0f, + 0x0a, 0x14, 0x04, 0x0f, 0x0b, 0x05, 0x0f, 0x18, 0x04, 0x18, + 0x09, 0x05, 0x06, 0x1b, 0x04, 0x13, 0x19, 0x0c, 0x1b, 0x0c, + 0x18, 0x19, 0x08, 0x0e, 0x11, 0x0b, 0x03, 0x16, 0x1b, 0x15, + 0x11, 0x14, 0x09, 0x09, 0x17, 0x0e, 0x12, 0x1a, 0x14, 0x12, + 0x19, 0x08, 0x16, 0x07, 0x12, 0x0a, 0x17, 0x14, 0x13, 0x06, + 0x10, 0x0f, 0x03, 0x18, 0x0d, 0x04, 0x13, 0x10, 0x1b, 0x03, + 0x09, }; static int T2[] = { - 0x16, 0x04, 0x18, 0x10, 0x13, 0x0f, 0x08, 0x19, 0x19, 0x17, - 0x13, 0x0b, 0x0b, 0x08, 0x0a, 0x08, 0x01, 0x05, 0x15, 0x1a, - 0x11, 0x02, 0x16, 0x0f, 0x0d, 0x09, 0x16, 0x13, 0x17, 0x0d, - 0x05, 0x11, 0x11, 0x0d, 0x05, 0x14, 0x01, 0x19, 0x12, 0x0a, - 0x15, 0x15, 0x15, 0x17, 0x13, 0x15, 0x0e, 0x18, 0x11, 0x0f, - 0x03, 0x04, 0x03, 0x09, 0x1a, 0x13, 0x04, 0x08, 0x09, 0x07, - 0x15, 0x16, 0x05, 0x11, 0x02, 0x00, 0x15, 0x10, 0x1b, 0x0d, - 0x14, 0x18, 0x10, 0x0f, 0x13, 0x13, 0x14, 0x11, 0x10, 0x0a, - 0x05, 0x03, 0x1a, 0x14, 0x0d, 0x19, 0x05, 0x1a, 0x1a, 0x00, - 0x06, 0x0c, 0x07, 0x11, 0x01, 0x18, 0x12, 0x06, 0x02, 0x06, - 0x1a, 0x17, 0x03, 0x0d, 0x09, 0x02, 0x09, 0x19, 0x03, 0x01, - 0x16, 0x0d, 0x17, 0x10, 0x01, 0x06, 0x18, 0x06, 0x10, 0x16, - 0x07, 0x06, 0x12, 0x1a, 0x17, 0x04, 0x16, 0x19, 0x0a, 0x1b, - 0x15, 0x16, 0x13, 0x11, 0x09, 0x1b, 0x02, 0x05, 0x12, 0x0c, - 0x10, 0x11, 0x08, 0x0f, 0x0c, 0x05, 0x0d, 0x0f, 0x19, 0x01, - 0x1b, 0x17, 0x03, 0x08, 0x00, 0x1a, 0x0d, 0x0c, 0x07, 0x19, - 0x17, 0x01, 0x03, 0x0e, 0x02, 0x18, 0x19, 0x10, 0x02, 0x00, - 0x0c, 0x02, 0x0a, 0x0b, 0x1a, 0x11, 0x19, 0x01, 0x16, 0x02, - 0x09, 0x01, 0x10, 0x1a, 0x0c, 0x0c, 0x12, 0x10, 0x18, 0x1b, - 0x14, 0x17, 0x17, 0x12, 0x1b, 0x08, 0x0d, 0x0c, 0x07, 0x1a, - 0x04, 0x03, 0x0b, 0x0e, 0x1b, 0x16, 0x10, 0x08, 0x17, 0x16, - 0x16, 0x10, 0x17, 0x0a, 0x1a, 0x0c, 0x17, 0x0f, 0x0a, 0x19, - 0x00, 0x0c, 0x08, 0x11, 0x17, 0x09, 0x17, 0x0f, 0x00, 0x05, - 0x17, 0x05, 0x05, 0x17, 0x17, 0x15, 0x0f, 0x00, 0x00, 0x19, - 0x0c, 0x19, 0x0f, 0x11, 0x08, 0x18, 0x01, 0x10, 0x17, 0x17, - 0x0d, 0x18, 0x13, 0x15, 0x0d, 0x0e, 0x0e, 0x09, 0x05, 0x17, - 0x14, 0x17, 0x16, 0x16, 0x1b, 0x10, 0x10, 0x0c, 0x06, 0x02, - 0x17, 0x12, 0x05, 0x08, 0x12, 0x00, 0x0b, 0x17, 0x07, 0x12, - 0x08, 0x01, 0x18, 0x0a, 0x19, 0x16, 0x01, 0x0b, 0x12, 0x12, - 0x06, 0x0a, 0x0e, 0x0c, 0x10, 0x0d, 0x00, 0x04, 0x19, 0x12, - 0x06, + 0x16, 0x04, 0x18, 0x10, 0x13, 0x0f, 0x08, 0x19, 0x19, 0x17, + 0x13, 0x0b, 0x0b, 0x08, 0x0a, 0x08, 0x01, 0x05, 0x15, 0x1a, + 0x11, 0x02, 0x16, 0x0f, 0x0d, 0x09, 0x16, 0x13, 0x17, 0x0d, + 0x05, 0x11, 0x11, 0x0d, 0x05, 0x14, 0x01, 0x19, 0x12, 0x0a, + 0x15, 0x15, 0x15, 0x17, 0x13, 0x15, 0x0e, 0x18, 0x11, 0x0f, + 0x03, 0x04, 0x03, 0x09, 0x1a, 0x13, 0x04, 0x08, 0x09, 0x07, + 0x15, 0x16, 0x05, 0x11, 0x02, 0x00, 0x15, 0x10, 0x1b, 0x0d, + 0x14, 0x18, 0x10, 0x0f, 0x13, 0x13, 0x14, 0x11, 0x10, 0x0a, + 0x05, 0x03, 0x1a, 0x14, 0x0d, 0x19, 0x05, 0x1a, 0x1a, 0x00, + 0x06, 0x0c, 0x07, 0x11, 0x01, 0x18, 0x12, 0x06, 0x02, 0x06, + 0x1a, 0x17, 0x03, 0x0d, 0x09, 0x02, 0x09, 0x19, 0x03, 0x01, + 0x16, 0x0d, 0x17, 0x10, 0x01, 0x06, 0x18, 0x06, 0x10, 0x16, + 0x07, 0x06, 0x12, 0x1a, 0x17, 0x04, 0x16, 0x19, 0x0a, 0x1b, + 0x15, 0x16, 0x13, 0x11, 0x09, 0x1b, 0x02, 0x05, 0x12, 0x0c, + 0x10, 0x11, 0x08, 0x0f, 0x0c, 0x05, 0x0d, 0x0f, 0x19, 0x01, + 0x1b, 0x17, 0x03, 0x08, 0x00, 0x1a, 0x0d, 0x0c, 0x07, 0x19, + 0x17, 0x01, 0x03, 0x0e, 0x02, 0x18, 0x19, 0x10, 0x02, 0x00, + 0x0c, 0x02, 0x0a, 0x0b, 0x1a, 0x11, 0x19, 0x01, 0x16, 0x02, + 0x09, 0x01, 0x10, 0x1a, 0x0c, 0x0c, 0x12, 0x10, 0x18, 0x1b, + 0x14, 0x17, 0x17, 0x12, 0x1b, 0x08, 0x0d, 0x0c, 0x07, 0x1a, + 0x04, 0x03, 0x0b, 0x0e, 0x1b, 0x16, 0x10, 0x08, 0x17, 0x16, + 0x16, 0x10, 0x17, 0x0a, 0x1a, 0x0c, 0x17, 0x0f, 0x0a, 0x19, + 0x00, 0x0c, 0x08, 0x11, 0x17, 0x09, 0x17, 0x0f, 0x00, 0x05, + 0x17, 0x05, 0x05, 0x17, 0x17, 0x15, 0x0f, 0x00, 0x00, 0x19, + 0x0c, 0x19, 0x0f, 0x11, 0x08, 0x18, 0x01, 0x10, 0x17, 0x17, + 0x0d, 0x18, 0x13, 0x15, 0x0d, 0x0e, 0x0e, 0x09, 0x05, 0x17, + 0x14, 0x17, 0x16, 0x16, 0x1b, 0x10, 0x10, 0x0c, 0x06, 0x02, + 0x17, 0x12, 0x05, 0x08, 0x12, 0x00, 0x0b, 0x17, 0x07, 0x12, + 0x08, 0x01, 0x18, 0x0a, 0x19, 0x16, 0x01, 0x0b, 0x12, 0x12, + 0x06, 0x0a, 0x0e, 0x0c, 0x10, 0x0d, 0x00, 0x04, 0x19, 0x12, + 0x06, }; #define uchar unsigned char @@ -1177,29 +1179,29 @@ static int T2[] = { static int tok_hash(const uchar *key) { - int i; - unsigned f0, f1, f2; - const uchar *kp = key; - - for (i=-47, f0=f1=f2=0; *kp; ++kp) { - if (*kp < 47 || *kp > 89) - return -1; - if (kp-key > 6) - return -1; - f0 += T0[i + *kp]; - f1 += T1[i + *kp]; - f2 += T2[i + *kp]; - i += 43; - } + int i; + unsigned f0, f1, f2; + const uchar *kp = key; + + for (i=-47, f0=f1=f2=0; *kp; ++kp) { + if (*kp < 47 || *kp > 89) + return -1; + if (kp-key > 6) + return -1; + f0 += T0[i + *kp]; + f1 += T1[i + *kp]; + f2 += T2[i + *kp]; + i += 43; + } - if (kp-key < 2) - return -1; + if (kp-key < 2) + return -1; - f0 %= 28; - f1 %= 28; - f2 %= 28; + f0 %= 28; + f1 %= 28; + f2 %= 28; - return (g[f0] + g[f1] + g[f2]) % 22; + return (g[f0] + g[f1] + g[f2]) % 22; } static void tokmap_insert(struct token_t *tok) @@ -1229,119 +1231,124 @@ static void init_globals(void) memset(var_map, 0, sizeof(var_map)); } -void ducky_main(int fd, bool verbose) +int ducky_interp(int fd, bool verbose) { - init_globals(); - - if(verbose) + if(!setjmp(exit_point)) { - vid_write("*** DS-2 INIT ***"); - vid_write("QUACK AT YOUR OWN RISK!"); - vid_write("The author assumes no liability for any damages caused by this program."); - } + init_globals(); - file_des = fd; + if(verbose) + { + vid_write("*** DS-2 INIT ***"); + vid_write("QUACK AT YOUR OWN RISK!"); + vid_write("The author assumes no liability for any damages caused by this program."); + } - atexit(exit_handler); + file_des = fd; - if(file_des < 0) - error("invalid file"); + atexit(exit_handler); - init_optable(); - init_tokmap(); + if(file_des < 0) + error("invalid file"); - /* initialize the "." variable, which is the line counter */ - setVariable(".", 0); - setConst(".", true); + init_optable(); + init_tokmap(); - struct varnode_t *dot_var = lookup_var("."); + /* initialize the "." variable, which is the line counter */ + setVariable(".", 0); + setConst(".", true); - /* initialize some other constants */ - setVariable("true", 1); - setConst("true", true); + struct varnode_t *dot_var = lookup_var("."); - setVariable("false", 0); - setConst("false", true); + /* initialize some other constants */ + setVariable("true", 1); + setConst("true", true); - line_offset = index_lines(file_des, &num_lines); - if(verbose) - { - vid_writef("Indexing complete (%u lines).", num_lines); - - vid_write("Executing..."); - } - int repeats_left = 0; + setVariable("false", 0); + setConst("false", true); - while(1) - { - char instr_buf[MAX_LINE_LEN]; - memset(instr_buf, 0, sizeof(instr_buf)); - if(read_line(file_des, instr_buf, sizeof(instr_buf)) <= 0) + line_offset = index_lines(file_des, &num_lines); + if(verbose) { - if(verbose) - vid_writef("end of file"); - goto done; + vid_writef("Indexing complete (%u lines).", num_lines); + + vid_write("Executing..."); } - char *tok = NULL, *save = NULL; + int repeats_left = 0; - ++current_line; - dot_var->val = current_line; - ++lines_executed; + while(1) + { + char instr_buf[MAX_LINE_LEN]; + memset(instr_buf, 0, sizeof(instr_buf)); + if(read_line(file_des, instr_buf, sizeof(instr_buf)) <= 0) + { + if(verbose) + vid_writef("end of file"); + goto done; + } + char *tok = NULL, *save = NULL; - char *buf = instr_buf; + ++current_line; + dot_var->val = current_line; + ++lines_executed; - /* execute all the commands on this line/instruction */ - do { - tok = strtok_r(buf, " -\t", &save); - buf = NULL; + char *buf = instr_buf; - if(!tok) - break; + /* execute all the commands on this line/instruction */ + do { + tok = strtok_r(buf, " -\t", &save); + buf = NULL; - int hash = tok_hash(tok) % TOKMAP_SIZE; - struct token_t *t = tokmap+hash; - if(hash >= 0 && strcmp(t->tok, tok) == 0) - switch(tokmap[hash].func(&save, &repeats_left)) - { - case OK: + if(!tok) break; - case BREAK: - goto break_out; - case DONE: - goto done; - case NEXT: + + int hash = tok_hash(tok) % TOKMAP_SIZE; + struct token_t *t = tokmap+hash; + if(hash >= 0 && strcmp(t->tok, tok) == 0) + switch(tokmap[hash].func(&save, &repeats_left)) + { + case OK: + break; + case BREAK: + goto break_out; + case DONE: + goto done; + case NEXT: + goto next_line; + default: + error("FIXME: invalid return value"); + } + else if(tok[0] == '#') goto next_line; - default: - error("FIXME: invalid return value"); + else + { + error("unknown token `%s` on line %d %d", tok, current_line); + goto done; } - else if(tok[0] == '#') - goto next_line; - else + } while(tok); + break_out: +#if 0 + if(repeats_left > 0) { - error("unknown token `%s` on line %d %d", tok, current_line); - goto done; - } - } while(tok); - break_out: - #if 0 - if(repeats_left > 0) - { - --repeats_left; - if(repeats_left) - jump_line(file_des, current_line); - else - { - if(current_line + 2 > num_lines) - goto done; - jump_line(file_des, current_line + 2); + --repeats_left; + if(repeats_left) + jump_line(file_des, current_line); + else + { + if(current_line + 2 > num_lines) + goto done; + jump_line(file_des, current_line + 2); + } } +#endif + next_line: + ; } - #endif - next_line: - ; - } -done: + done: - return; + return 0; + } + else + return 1; } @@ -7,26 +7,27 @@ #define CALLSTACK_SZ 64 #define MAX_VARS 65536 -imm_t callstack[CALLSTACK_SZ]; -unsigned callstack_pointer; +static imm_t callstack[CALLSTACK_SZ]; +static unsigned callstack_pointer; -imm_t stack[STACK_SZ]; -unsigned stack_pointer; +static imm_t stack[STACK_SZ]; +static unsigned stack_pointer; +static jmp_buf exit_point; struct var_t { vartype val; bool constant; }; -struct var_t vars[MAX_VARS]; -int file_des; -unsigned current_line, num_lines; +static struct var_t vars[MAX_VARS]; +static int file_des; +static unsigned current_line, num_lines; -off_t *line_offset; +static off_t *line_offset; -bool want_quit; -int repeats_left; -imm_t repeat_line; +static bool want_quit; +static int repeats_left; +static imm_t repeat_line; static void error(const char *fmt, ...) __attribute__((noreturn,format(print,1,2))); static void vid_write(const char *str); @@ -92,7 +93,7 @@ static void __attribute__((noreturn,format(printf,1,2))) error(const char *fmt, vid_writef("ERROR: %s\n", fmtbuf); va_end(ap); - exit(EXIT_FAILURE); + longjmp(exit_point, 1); } static void __attribute__((format(printf,1,2))) warning(const char *fmt, ...) @@ -163,41 +164,41 @@ static inline void jump(imm_t line) error("jump target out of bounds"); } -void pushimm_handler(void) +static void pushimm_handler(void) { push(read_imm()); } -void pushvar_handler(void) +static void pushvar_handler(void) { push(getvar(read_varid())); } -void pop_handler(void) +static void pop_handler(void) { setvar(read_varid(), pop()); } -void mkconst_handler(void) +static void mkconst_handler(void) { mkconst(read_varid()); } -void incvar_handler(void) +static void incvar_handler(void) { varid_t varid = read_varid(); if(varid < ARRAYLEN(vars)) ++vars[varid].val; } -void decvar_handler(void) +static void decvar_handler(void) { varid_t varid = read_varid(); if(varid < ARRAYLEN(vars)) --vars[varid].val; } -void writestr_handler(void) +static void writestr_handler(void) { while(1) { @@ -209,7 +210,7 @@ void writestr_handler(void) } } -void repeat_handler(void) +static void repeat_handler(void) { if(repeats_left > 0) { @@ -229,12 +230,12 @@ void repeat_handler(void) } } -void jump_handler(void) +static void jump_handler(void) { jump(pop()); } -void subcall_handler(void) +static void subcall_handler(void) { if(callstack_pointer < CALLSTACK_SZ) { @@ -245,7 +246,7 @@ void subcall_handler(void) error("call stack overflow"); } -void subret_handler(void) +static void subret_handler(void) { if(callstack_pointer > 0) { @@ -255,14 +256,14 @@ void subret_handler(void) error("call stack underflow"); } -void if_handler(void) +static void if_handler(void) { imm_t line = pop(); if(!pop()) jump(line); } -void delay_handler(void) +static void delay_handler(void) { imm_t ms = pop(); @@ -272,22 +273,22 @@ void delay_handler(void) nanosleep(&t, NULL); } -void logvar_handler(void) +static void logvar_handler(void) { vid_writef(VARFORMAT, pop()); } -void quit_handler(void) +static void quit_handler(void) { want_quit = true; } -void logascii_handler(void) +static void logascii_handler(void) { vid_writef("%c", pop()); } -void neg_handler(void) +static void neg_handler(void) { stack[stack_pointer - 1] = -stack[stack_pointer - 1]; } @@ -297,155 +298,155 @@ static vartype eval_exp(vartype a1, vartype a2) return a2<0 ? 0 : (a2==0?1:a1*eval_exp(a1, a2-1)); } -void pow_handler(void) +static void pow_handler(void) { imm_t pow = pop(); imm_t base = pop(); push(eval_exp(base, pow)); } -void mul_handler(void) +static void mul_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a*b); } -void div_handler(void) +static void div_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a/b); } -void mod_handler(void) +static void mod_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a%b); } -void add_handler(void) +static void add_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a+b); } -void sub_handler(void) +static void sub_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a-b); } -void eq_handler(void) +static void eq_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a==b); } -void neq_handler(void) +static void neq_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a!=b); } -void leq_handler(void) +static void leq_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a<=b); } -void geq_handler(void) +static void geq_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a>=b); } -void lt_handler(void) +static void lt_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a<b); } -void gt_handler(void) +static void gt_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a>b); } -void lognot_handler(void) +static void lognot_handler(void) { push(!pop()); } -void logand_handler(void) +static void logand_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a&&b); } -void logor_handler(void) +static void logor_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a||b); } -void bitand_handler(void) +static void bitand_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a&b); } -void bitor_handler(void) +static void bitor_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a|b); } -void bitxor_handler(void) +static void bitxor_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a^b); } -void bitcomp_handler(void) +static void bitcomp_handler(void) { push(~pop()); } -void lsh_handler(void) +static void lsh_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a<<b); } -void rsh_handler(void) +static void rsh_handler(void) { imm_t b = pop(); imm_t a = pop(); push(a>>b); } -void sqrt_handler(void) +static void sqrt_handler(void) { push(sqrt(pop())); } -void decl_const(void) +static void decl_const(void) { /* no checking, only the compiler can output this instruction */ varid_t varid = read_varid(); @@ -453,12 +454,12 @@ void decl_const(void) vars[varid].constant = true; } -void newline_handler(void) +static void newline_handler(void) { vid_writef("\n"); } -void inc_line_pointer(void) +static void inc_line_pointer(void) { ++current_line; @@ -724,32 +725,38 @@ static void (*instr_tab[0x100])(void) = { inc_line_pointer, /* 0xff */ }; -void ducky_vm(int fd) +int ducky_vm(int fd) { - file_des = fd; + if(!setjmp(exit_point)) + { + file_des = fd; - init_globals(); + init_globals(); - if(read_imm() != DUCKY_MAGIC) - error("unknown format"); + if(read_imm() != DUCKY_MAGIC) + error("unknown format"); - num_lines = read_imm(); - line_offset = malloc(num_lines + 1); - for(unsigned int i = 1; i <= num_lines; ++i) - { - line_offset[i] = read_imm(); - } + num_lines = read_imm(); + line_offset = malloc(num_lines + 1); + for(unsigned int i = 1; i <= num_lines; ++i) + { + line_offset[i] = read_imm(); + } - /* and... execute! */ - while(!want_quit) - { - instr_t instr = read_instr(); - if(want_quit) - break; - void (*handler)(void) = instr_tab[instr]; - if(handler) - handler(); - else - error("invalid instruction"); + /* and... execute! */ + while(!want_quit) + { + instr_t instr = read_instr(); + if(want_quit) + break; + void (*handler)(void) = instr_tab[instr]; + if(handler) + handler(); + else + error("invalid instruction"); + } + return 0; } + else + return 1; } |