diff options
Diffstat (limited to 'vxrefbas.c')
-rw-r--r-- | vxrefbas.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/vxrefbas.c b/vxrefbas.c new file mode 100644 index 0000000..1c4e1ab --- /dev/null +++ b/vxrefbas.c @@ -0,0 +1,167 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <time.h> + +#include "bas.h" + +int A, F, N, D, I, R, G, O, L; +int target_var, lastline; +unsigned char last_cmd = 0; +int refcounts[128]; + +void print_help(void) { + printf("Usage: %s [-v] program.bas\n", self); + exit(0); +} + +CALLBACK(new_line) { + A = F = N = D = I = R = G = O = L = 0; +} + +CALLBACK(end_line) { + if(lastline != lineno) return; + + if(A || F || N || D || I || R || G || O || L) { + putchar('='); + if(A) putchar('A'); + if(F) putchar('F'); + if(N) putchar('N'); + if(D) putchar('D'); + if(I) putchar('I'); + if(R) putchar('R'); + if(G) putchar('G'); + if(O) putchar('O'); + if(L) putchar('L'); + } + + putchar(' '); +} + +CALLBACK(new_command) { + last_cmd = tok; +} + +CALLBACK(end_stmt) { + last_cmd = 0; +} + +CALLBACK(handle_var) { + unsigned char last_tok, next_tok; + int was_cmd, was_comma, was_semicolon; + + if(tok != (target_var | 0x80)) return; + + if(lastline != lineno) { + printf("%d", lineno); + refcounts[target_var]++; + } + + lastline = lineno; + + last_tok = program[pos - 1]; + next_tok = program[pos + 1]; + was_cmd = (last_tok == last_cmd); + was_comma = (last_tok == OP_COMMA); + was_semicolon = (last_tok == OP_SEMICOLON); + + switch(last_cmd) { + case CMD_LET: + case CMD_ILET: + if(was_cmd) A = 1; + break; + case CMD_FOR: + if(was_cmd) F = 1; + break; + case CMD_NEXT: + if(was_cmd) N = 1; + break; + case CMD_DIM: + if(was_cmd || was_comma) D = 1; + break; + case CMD_INPUT: /* INPUT #1;A and INPUT #1,A are both allowed, grr. */ + if(was_cmd || was_comma || was_semicolon) I = 1; + break; + case CMD_READ: + if(was_cmd || was_comma) R = 1; + break; + case CMD_GET: + if(was_comma) G = 1; + break; + case CMD_NOTE: + if(was_comma) O = 1; + break; + case CMD_LOCATE: + if(next_tok == OP_EOS || next_tok == OP_EOL) L = 1; + break; + } +} + +void parse_args(int argc, char **argv) { + int opt; + + while( (opt = getopt(argc, argv, "v")) != -1) { + switch(opt) { + case 'v': verbose = 1; break; + default: print_help(); exit(1); + } + } + + if(optind >= argc) + die("No input file given (use - for stdin)."); + else + open_input(argv[optind]); +} + +int main(int argc, char **argv) { + unsigned short pos; + unsigned short vnpos; + int unref = 0; + + set_self(*argv); + parse_general_args(argc, argv, print_help); + parse_args(argc, argv); + + readfile(); + parse_header(); + + if(!vntable_ok()) + die("Program is variable-protected; unprotect it first."); + + on_var_token = handle_var; + on_start_line = new_line; + on_end_line = end_line; + on_cmd_token = new_command; + on_end_stmt = end_stmt; + + target_var = 0; + vnpos = vnstart; + + /* walk the variable value table */ + for(pos = vvstart; pos < codestart; pos += 8) { + /* print the variable name */ + while(program[vnpos] < 0x80) + putchar(program[vnpos++]); + putchar(program[vnpos++] & 0x7f); + printf("/%02x: ", target_var | 0x80); + + lastline = -1; + walk_all_code(); + + if(!refcounts[target_var]) { + unref++; + printf("(no references)"); + } else { + printf("(%d)", refcounts[target_var]); + } + putchar('\n'); + + /* ignore any ERROR-4 vars, since they don't have tokens anyway. */ + if(++target_var == 128) break; + } + + printf(" %d variables, %d unreferenced.\n", target_var, unref); + return 0; +} |