From a7ee96f24543d6382f09a51418391b9b8a957fda Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 17 Jun 2024 20:59:44 -0400 Subject: cxrefbas: break out table building stuff for use with renumbas. --- linetab.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 linetab.c (limited to 'linetab.c') diff --git a/linetab.c b/linetab.c new file mode 100644 index 0000000..c4fe392 --- /dev/null +++ b/linetab.c @@ -0,0 +1,165 @@ +#include "linetab.h" + +lineref_t *linerefs[32769]; +int refcounts[32769]; +int lines_exist[32769]; +unsigned char last_cmd, on_op; +int last_cmd_pos; + +void add_lineref(unsigned short from, unsigned short pos) { + lineref_t *p; + int c; + unsigned short to; + + to = fp2int(program + pos); + if(to > 32767) return; + + p = linerefs[to]; + c = refcounts[to]; + + if(c) { + p = realloc(p, sizeof(lineref_t) * (c + 1)); + } else { + p = malloc(sizeof(lineref_t)); + } + + if(!p) die("Out of memory."); + + linerefs[to] = p; + linerefs[to][c].lineno = from; + linerefs[to][c].pos = pos; + linerefs[to][c].cmd = last_cmd; + c++; + refcounts[to] = c; +} + +/* makes sure a numeric constant isn't start of an expression. */ +int is_standalone_num(unsigned short pos) { + if(program[pos] != OP_NUMCONST) return 0; + switch(program[pos + 7]) { + case OP_EOS: + case OP_EOL: + case OP_COMMA: + return 1; + default: + return 0; + } +} + +CALLBACK(start_stmt) { + lines_exist[lineno] = 1; +} + +CALLBACK(got_cmd) { + last_cmd = tok; + last_cmd_pos = pos; + on_op = 0; +} + +void computed_msg(unsigned short lineno) { + static int last_lineno = -1; + char *cmd; + + /* avoid duplicate warnings */ + if(lineno == last_lineno) return; + last_lineno = lineno; + + switch(last_cmd) { + case CMD_GOTO: + cmd = "GOTO"; break; + case CMD_GO_TO: + cmd = "GO TO"; break; + case CMD_GOSUB: + cmd = "GOSUB"; break; + case CMD_RESTORE: + cmd = "RESTORE"; break; + case CMD_TRAP: + cmd = "TRAP"; break; + /* + case CMD_IF: + cmd = "IF/THEN"; break; + */ + case CMD_ON: + if(on_op == OP_GOSUB) + cmd = "ON/GOSUB"; + else + cmd = "ON/GOTO"; + break; + default: /* should never happen! */ + cmd = "???"; break; + } + + fprintf(stderr, "Computed %s at line %d\n", cmd, lineno); +} + +CALLBACK(got_var) { + switch(last_cmd) { + case CMD_GOTO: + case CMD_GO_TO: + case CMD_GOSUB: + case CMD_RESTORE: + case CMD_TRAP: + computed_msg(lineno); + break; + default: + break; + } +} + +CALLBACK(got_exp) { + unsigned char last_tok = program[pos - 1]; + int standalone; + + if(last_cmd == CMD_ON) { + if(tok == OP_GOTO || tok == OP_GOSUB) + on_op = tok; + } + + if(tok != OP_NUMCONST) return; + standalone = is_standalone_num(pos); + + switch(last_cmd) { + case CMD_GOTO: + case CMD_GO_TO: + case CMD_GOSUB: + case CMD_RESTORE: + case CMD_TRAP: + if((pos == last_cmd_pos + 1) && standalone) { + add_lineref(lineno, pos + 1); + } else { + computed_msg(lineno); + } + break; + case CMD_IF: + if(last_tok == OP_THEN) { + add_lineref(lineno, pos + 1); + } + break; + case CMD_ON: { + switch(last_tok) { + case OP_GOTO: + case OP_GOSUB: + case OP_COMMA: + if(standalone) + add_lineref(lineno, pos + 1); + else + computed_msg(lineno); + break; + default: + break; + } + } + break; + default: + break; + } +} + +void build_ref_table(void) { + on_start_stmt = start_stmt; + on_cmd_token = got_cmd; + on_exp_token = got_exp; + on_var_token = got_var; + walk_all_code(); +} + -- cgit v1.2.3