diff options
Diffstat (limited to 'bas.c')
-rw-r--r-- | bas.c | 105 |
1 files changed, 104 insertions, 1 deletions
@@ -155,6 +155,10 @@ void adjust_vntable_size(int oldsize, int newsize) { } } +unsigned char get_vartype(unsigned char tok) { + return program[vvstart + (tok & 0x7f) * 8] >> 6; +} + /* return true if the variable name table is OK */ int vntable_ok(void) { int vp, bad; @@ -249,10 +253,109 @@ void open_output(const char *name) { output_file = open_file(name, "wb"); } -extern void set_self(const char *argv0) { +void set_self(const char *argv0) { char *p; self = argv0; p = strrchr(self, '/'); if(p) self = p + 1; } + +/* callbacks */ +CALLBACK_PTR(on_start_line); +CALLBACK_PTR(on_bad_line_length); +CALLBACK_PTR(on_end_line); +CALLBACK_PTR(on_start_stmt); +CALLBACK_PTR(on_end_stmt); +CALLBACK_PTR(on_cmd_token); +CALLBACK_PTR(on_text); +CALLBACK_PTR(on_exp_token); +CALLBACK_PTR(on_var_token); +CALLBACK_PTR(on_string_const); +CALLBACK_PTR(on_num_const); + +#define CALL(x) if(x) (*x)(lineno, pos, program[pos], end) + +void walk_code(unsigned int startlineno, unsigned int endlineno) { + int linepos, nextpos, offset, soffset, lineno, pos, end, tok; + + linepos = codestart; + while(linepos < filelen) { /* loop over lines */ + lineno = getword(linepos); + offset = program[linepos + 2]; + nextpos = linepos + offset; + + end = nextpos; + pos = linepos; + + if(offset < 6) { + CALL(on_bad_line_length); + offset = program[linepos + 2]; /* on_bad_line_length fixed it (we hope) */ + if(offset < 6) + die("Program is code-protected; unprotect it first."); + } + + if(lineno < startlineno) { + linepos = nextpos; + continue; + } + + CALL(on_start_line); + + pos = linepos + 3; + while(pos < nextpos) { /* loop over statements within a line */ + soffset = program[pos]; + end = linepos + soffset; + CALL(on_start_stmt); + + while(pos < end) { /* loop over tokens within a statement */ + pos++; + CALL(on_cmd_token); + switch(program[pos]) { + case CMD_REM: + case CMD_DATA: + case CMD_ERROR: + pos++; + CALL(on_text); + pos = end; + break; + default: + pos++; + break; + } + + while(pos < end) { /* loop over operators */ + tok = program[pos]; + switch(tok) { + case OP_NUMCONST: + CALL(on_exp_token); + pos++; + CALL(on_num_const); + pos += 6; + break; + case OP_STRCONST: + CALL(on_exp_token); + pos++; + CALL(on_string_const); + pos += program[pos] + 1; + break; + default: + if(tok & 0x80) { + CALL(on_var_token); + } else { + CALL(on_exp_token); + } + pos++; + break; + } + } + CALL(on_end_stmt); + } + } + + CALL(on_end_line); + + if(lineno >= endlineno) break; + linepos = nextpos; + } +} |