aboutsummaryrefslogtreecommitdiff
path: root/src/compile.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2015-11-21 18:27:38 -0500
committerFranklin Wei <git@fwei.tk>2015-11-21 18:27:38 -0500
commitafc3e4b88e193025e49736e545ccb7765b19d1b5 (patch)
treeefb32f2b86739e38c466ee514f2cb6338fa99fe7 /src/compile.c
parent03a7066353fad59b7c29b57baa94f84bcc5cfcda (diff)
downloadducky-afc3e4b88e193025e49736e545ccb7765b19d1b5.zip
ducky-afc3e4b88e193025e49736e545ccb7765b19d1b5.tar.gz
ducky-afc3e4b88e193025e49736e545ccb7765b19d1b5.tar.bz2
ducky-afc3e4b88e193025e49736e545ccb7765b19d1b5.tar.xz
better error handling
Diffstat (limited to 'src/compile.c')
-rw-r--r--src/compile.c205
1 files changed, 106 insertions, 99 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;
}