From 5b4d161d5c82105f92006aa9cebbcd72b9383178 Mon Sep 17 00:00:00 2001
From: "B. Watson" <urchlay@slackware.uk>
Date: Sat, 15 Jun 2024 16:22:25 -0400
Subject: vxrefbas: WIP.

---
 bas.h        |  51 ++++++++++++++++--------------
 vxrefbas.1   |  65 +++-----------------------------------
 vxrefbas.c   | 100 +++++++++++++++++++++++++++++++++++++++--------------------
 vxrefbas.rst |  33 ++------------------
 4 files changed, 100 insertions(+), 149 deletions(-)

diff --git a/bas.h b/bas.h
index ce67309..c88d035 100644
--- a/bas.h
+++ b/bas.h
@@ -33,30 +33,33 @@
 /* BASIC tokens. Not a full set. BASIC uses 2 sets of tokens, one
    for commands and the other for operators (which is to say, everything
    *not* a command). */
-#define CMD_GOTO    0x0a
-#define CMD_GO_TO   0x0b
-#define CMD_GOSUB   0x0c
-#define CMD_TRAP    0x0d
-#define CMD_LIST    0x04
-#define CMD_RESTORE 0x23
-#define CMD_REM     0x00
-#define CMD_DATA    0x01
-#define CMD_ERROR   0x37
-#define CMD_FOR     0x08
-#define CMD_NEXT    0x09
-#define CMD_LET     0x06
-#define CMD_ILET    0x36
-#define CMD_DIM     0x14
-#define CMD_READ    0x22
-#define CMD_INPUT   0x02
-#define OP_GOTO     0x17
-#define OP_GOSUB    0x18
-#define OP_THEN     0x1b
-#define OP_COMMA    0x12
-#define OP_EOS      0x14
-#define OP_EOL      0x16
-#define OP_NUMCONST 0x0e
-#define OP_STRCONST 0x0f
+#define CMD_GOTO     0x0a
+#define CMD_GO_TO    0x0b
+#define CMD_GOSUB    0x0c
+#define CMD_TRAP     0x0d
+#define CMD_LIST     0x04
+#define CMD_RESTORE  0x23
+#define CMD_REM      0x00
+#define CMD_DATA     0x01
+#define CMD_ERROR    0x37
+#define CMD_FOR      0x08
+#define CMD_NEXT     0x09
+#define CMD_LET      0x06
+#define CMD_ILET     0x36
+#define CMD_DIM      0x14
+#define CMD_READ     0x22
+#define CMD_INPUT    0x02
+#define CMD_GET      0x29
+#define OP_GOTO      0x17
+#define OP_GOSUB     0x18
+#define OP_THEN      0x1b
+#define OP_COMMA     0x12
+#define OP_ARR_COMMA 0x3c
+#define OP_EOS       0x14
+#define OP_EOL       0x16
+#define OP_NUMCONST  0x0e
+#define OP_STRCONST  0x0f
+#define OP_HASH      0x1c
 
 /* variable types, bits 6-7 of byte 0 of each vvtable entry. */
 #define TYPE_SCALAR 0
diff --git a/vxrefbas.1 b/vxrefbas.1
index 17780d9..e139d59 100644
--- a/vxrefbas.1
+++ b/vxrefbas.1
@@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
 .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
 ..
-.TH "VXREFBAS" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "VXREFBAS" 1 "2024-06-15" "0.2.1" "Urchlay's Atari 8-bit Tools"
 .SH NAME
 vxrefbas \- Variable cross-reference for tokenized Atari 8-bit BASIC files
 .SH SYNOPSIS
@@ -68,6 +68,9 @@ Variable was \fIINPUT\fP on this line.
 .TP
 .B \fBR\fP
 Variable was \fIREAD\fP on this line.
+.TP
+.B \fBG\fP
+Variable was read with \fIGET\fP on this line.
 .UNINDENT
 .SH OPTIONS
 .SS General Options
@@ -83,66 +86,6 @@ Print version number and exit.
 Verbose operation. When displaying a number in verbose mode, it will
 be prefixed with \fI$\fP if it\(aqs in hex, or no prefix for decimal.
 .UNINDENT
-.SH BUGS
-.sp
-This program:
-.INDENT 0.0
-.INDENT 3.5
-.sp
-.nf
-.ft C
-10 FILE=1:INPUT #FILE,LINE$
-.ft P
-.fi
-.UNINDENT
-.UNINDENT
-.sp
-Results in this:
-.INDENT 0.0
-.INDENT 3.5
-.sp
-.nf
-.ft C
-FILE/80: 10=AI (1)
-LINE$/81: 10=AI (1)
-  2 variables, 0 unreferenced.
-.ft P
-.fi
-.UNINDENT
-.UNINDENT
-.sp
-\fBvxrefbas\fP thinks \fIFILE\fP is being \fIINPUT\fP on line 10, which it isn\(aqt.
-The output for \fIFILE\fP should read \fI10=A (1)\fP\&.
-.sp
-Also, this program:
-.INDENT 0.0
-.INDENT 3.5
-.sp
-.nf
-.ft C
-10 DIM A(1):A(0)=10
-20 DIM B(A(0))
-.ft P
-.fi
-.UNINDENT
-.UNINDENT
-.sp
-Results in this:
-.INDENT 0.0
-.INDENT 3.5
-.sp
-.nf
-.ft C
-A(/80: 10=AD 20=D (2)
-B(/81: 20=D (1)
-  2 variables, 0 unreferenced.
-.ft P
-.fi
-.UNINDENT
-.UNINDENT
-.sp
-\fBvxrefbas\fP thinks \fIA(\fP is being DIMensioned on line 20, which it isn\(aqt. The
-output for \fIA(\fP should read \fI10=AD 20 (2)\fP\&.
 .SH EXIT STATUS
 .sp
 0 for success, 1 for failure.
diff --git a/vxrefbas.c b/vxrefbas.c
index acc830c..e05e2d7 100644
--- a/vxrefbas.c
+++ b/vxrefbas.c
@@ -7,8 +7,9 @@
 
 #include "bas.h"
 
-int target_var, lastline, assign, is_for, is_next, is_dim, is_read, is_input;
-int in_dim, in_read, in_input;
+int A, F, N, D, I, R, G;
+int target_var, lastline;
+unsigned char last_cmd = 0, last_op = 0;
 int refcounts[128];
 
 void print_help(void) {
@@ -17,57 +18,87 @@ void print_help(void) {
 }
 
 CALLBACK(new_line) {
-	assign = is_for = is_next = is_dim = is_read = is_input = 0;
+	A = F = N = D = I = R = G = 0;
 }
 
 CALLBACK(end_line) {
 	if(lastline != lineno) return;
 
-	printf("%d", lineno);
-	if(assign || is_for || is_next || is_dim || is_read || is_input) {
+	if(A || F || N || D || I || R || G) {
 		putchar('=');
-		if(assign)   putchar('A');
-		if(is_for)   putchar('F');
-		if(is_next)  putchar('N');
-		if(is_dim)   putchar('D');
-		if(is_read)  putchar('R');
-		if(is_input) putchar('I');
+		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');
 	}
+
 	putchar(' ');
 }
 
 CALLBACK(new_command) {
-	switch(tok) {
+	last_cmd = tok;
+}
+
+CALLBACK(end_stmt) {
+	last_cmd = last_op = 0;
+}
+
+CALLBACK(handle_var) {
+	unsigned char last_tok;
+
+	if(tok != (target_var | 0x80)) return;
+
+	if(lastline != lineno) {
+		printf("%d", lineno);
+		refcounts[target_var]++;
+	}
+
+	lastline = lineno;
+	last_tok = program[pos - 1];
+
+	switch(last_cmd) {
 		case CMD_LET:
 		case CMD_ILET:
-			assign = 1; break;
+			if(last_tok == last_cmd) A = 1;
+			break;
 		case CMD_FOR:
-			is_for = 1; break;
+			if(last_tok == last_cmd) F = 1;
+			break;
 		case CMD_NEXT:
-			is_next = 1; break;
+			if(last_tok == last_cmd) N = 1;
+			break;
 		case CMD_DIM:
-			in_dim = 1; break;
-		case CMD_READ:
-			in_read= 1; break;
+			if(last_tok == last_cmd || last_tok == OP_COMMA) D = 1;
+			break;
 		case CMD_INPUT:
-			in_input= 1; break;
-		default: break;
+			if(last_tok == last_cmd || last_tok == OP_COMMA) I = 1;
+			break;
+		case CMD_READ:
+			if(last_tok == last_cmd || last_tok == OP_COMMA) R = 1;
+			break;
+		case CMD_GET:
+			if(last_tok == OP_COMMA) G = 1;
+			break;
 	}
 }
 
-CALLBACK(end_stmt) {
-	in_dim = in_read = in_input = 0;
-}
+void parse_args(int argc, char **argv) {
+	int opt;
 
-CALLBACK(handle_var) {
-	if(in_dim) is_dim = 1;
-	if(in_input) is_input = 1;
-	if(in_read) is_read = 1;
-	if(lastline == lineno) return;
-	if((tok & 0x7f) == target_var) {
-		refcounts[target_var]++;
-		lastline = lineno;
+	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) {
@@ -77,8 +108,7 @@ int main(int argc, char **argv) {
 
 	set_self(*argv);
 	parse_general_args(argc, argv, print_help);
-
-	open_input(argv[1]);
+	parse_args(argc, argv);
 
 	readfile();
 	parse_header();
@@ -92,6 +122,7 @@ int main(int argc, char **argv) {
 	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)
@@ -110,7 +141,8 @@ int main(int argc, char **argv) {
 		}
 		putchar('\n');
 
-		if(target_var++ == 128) break;
+		/* 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);
diff --git a/vxrefbas.rst b/vxrefbas.rst
index 510d016..2e18186 100644
--- a/vxrefbas.rst
+++ b/vxrefbas.rst
@@ -49,6 +49,9 @@ which show the type of variable access.
 **R**
   Variable was *READ* on this line.
 
+**G**
+  Variable was read with *GET* on this line.
+
 OPTIONS
 =======
 
@@ -64,36 +67,6 @@ General Options
   Verbose operation. When displaying a number in verbose mode, it will
   be prefixed with *$* if it's in hex, or no prefix for decimal.
 
-BUGS
-====
-
-This program::
-
-  10 FILE=1:INPUT #FILE,LINE$
-
-Results in this::
-
-  FILE/80: 10=AI (1)
-  LINE$/81: 10=AI (1)
-    2 variables, 0 unreferenced.
-
-**vxrefbas** thinks *FILE* is being *INPUT* on line 10, which it isn't.
-The output for *FILE* should read *10=A (1)*.
-
-Also, this program::
-
-  10 DIM A(1):A(0)=10
-  20 DIM B(A(0))
-
-Results in this::
-
-  A(/80: 10=AD 20=D (2)
-  B(/81: 20=D (1)
-    2 variables, 0 unreferenced.
-
-**vxrefbas** thinks *A(* is being DIMensioned on line 20, which it isn't. The
-output for *A(* should read *10=AD 20 (2)*.
-
 EXIT STATUS
 ===========
 
-- 
cgit v1.2.3