aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compile.c205
-rw-r--r--src/ducky.h10
-rw-r--r--src/emitc.c79
-rw-r--r--src/interp.c417
-rw-r--r--src/vm.c159
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;
}
diff --git a/src/vm.c b/src/vm.c
index 8f68acd..37a7fd1 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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;
}