aboutsummaryrefslogtreecommitdiff
path: root/bas.c
diff options
context:
space:
mode:
Diffstat (limited to 'bas.c')
-rw-r--r--bas.c105
1 files changed, 104 insertions, 1 deletions
diff --git a/bas.c b/bas.c
index e90d96c..fc5517b 100644
--- a/bas.c
+++ b/bas.c
@@ -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;
+ }
+}