aboutsummaryrefslogtreecommitdiff
path: root/vxrefbas.c
diff options
context:
space:
mode:
Diffstat (limited to 'vxrefbas.c')
-rw-r--r--vxrefbas.c167
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;
+}