#include #include #include #include #include #include #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) { fprintf(stderr, "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; }