aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-06-13 15:30:33 -0400
committerB. Watson <urchlay@slackware.uk>2024-06-13 15:30:33 -0400
commit9d1ce7321f27d47b76cba907127af777d6672188 (patch)
tree9d0af044cbead9f251cbf401f5664d6c766edb72
parent79cbc8914d90ced367b68c4aaf899dfe596449a3 (diff)
downloadbw-atari8-tools-9d1ce7321f27d47b76cba907127af777d6672188.tar.gz
major surgery: callback API, port dumpbas to use callbacks, add vxrefbas.
-rw-r--r--Makefile6
-rw-r--r--a8eol.13
-rw-r--r--a8utf8.13
-rw-r--r--atascii.73
-rw-r--r--atr2xfd.13
-rw-r--r--atrsize.13
-rw-r--r--axe.13
-rw-r--r--bas.c105
-rw-r--r--bas.h24
-rw-r--r--blob2c.13
-rw-r--r--blob2xex.13
-rw-r--r--cart2xex.13
-rw-r--r--dasm2atasm.13
-rw-r--r--dumpbas.13
-rw-r--r--dumpbas.c112
-rw-r--r--fenders.13
-rw-r--r--manftr.rst1
-rw-r--r--rom2cart.13
-rw-r--r--unmac65.13
-rw-r--r--unprotbas.13
-rw-r--r--vxrefbas.1113
-rw-r--r--vxrefbas.c95
-rw-r--r--vxrefbas.rst57
-rw-r--r--xex.53
-rw-r--r--xex1to2.13
-rw-r--r--xexamine.13
-rw-r--r--xexcat.13
-rw-r--r--xexsplit.13
-rw-r--r--xfd2atr.13
29 files changed, 552 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index e5f86f9..8bd3ebf 100644
--- a/Makefile
+++ b/Makefile
@@ -16,9 +16,9 @@ CC=gcc
CFLAGS=-Wall $(COPT) -ansi -D_GNU_SOURCE -DVERSION=\"$(VERSION)\"
# BINS and SCRIPTS go in $BINDIR, DOCS go in $DOCDIR
-BINS=a8eol atr2xfd atrsize axe blob2c blob2xex cart2xex dumpbas fenders protbas renumbas rom2cart unmac65 unprotbas xex1to2 xexamine xexcat xexsplit xfd2atr
+BINS=a8eol atr2xfd atrsize axe blob2c blob2xex cart2xex dumpbas fenders protbas renumbas rom2cart unmac65 unprotbas vxrefbas xex1to2 xexamine xexcat xexsplit xfd2atr
SCRIPTS=dasm2atasm a8utf8
-MANS=a8eol.1 xfd2atr.1 atr2xfd.1 blob2c.1 cart2xex.1 fenders.1 xexsplit.1 xexcat.1 atrsize.1 rom2cart.1 unmac65.1 axe.1 dasm2atasm.1 a8utf8.1 blob2xex.1 xexamine.1 xex1to2.1 unprotbas.1 protbas.1 renumbas.1 dumpbas.1
+MANS=a8eol.1 xfd2atr.1 atr2xfd.1 blob2c.1 cart2xex.1 fenders.1 xexsplit.1 xexcat.1 atrsize.1 rom2cart.1 unmac65.1 axe.1 dasm2atasm.1 a8utf8.1 blob2xex.1 xexamine.1 xex1to2.1 unprotbas.1 protbas.1 renumbas.1 dumpbas.1 vxrefbas.1
MAN5S=xex.5
MAN7S=atascii.7
DOCS=README.txt equates.inc *.dasm LICENSE ksiders/atr.txt
@@ -57,6 +57,8 @@ renumbas: bas.o
dumpbas: bas.o
+vxrefbas: bas.o
+
bas.o: bas.c bas.h
subdirs:
diff --git a/a8eol.1 b/a8eol.1
index 5aca5dc..a68ed2b 100644
--- a/a8eol.1
+++ b/a8eol.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 "A8EOL" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "A8EOL" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
a8eol \- convert Atari 8-bit text files to/from UNIX/Windows/Mac
.\" RST source for a8eol(1) man page. Convert with:
@@ -478,6 +478,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/a8utf8.1 b/a8utf8.1
index 6e57a98..ada18ea 100644
--- a/a8utf8.1
+++ b/a8utf8.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 "A8UTF8" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "A8UTF8" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
a8utf8 \- Convert Atari 8-bit text to UTF-8 encoded Unicode.
.\" RST source for a8utf8(1) man page. Convert with:
@@ -109,6 +109,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/atascii.7 b/atascii.7
index bda5be6..7032d78 100644
--- a/atascii.7
+++ b/atascii.7
@@ -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 "ATASCII" 7 "2024-06-09" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "ATASCII" 7 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
atascii \- Atari 8-bit character set
.\" RST source for atascii(7) man page. Convert with:
@@ -2167,6 +2167,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/atr2xfd.1 b/atr2xfd.1
index ad6e217..e4a91e9 100644
--- a/atr2xfd.1
+++ b/atr2xfd.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 "ATR2XFD" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "ATR2XFD" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
atr2xfd \- Convert an Atari 8-bit ATR disk image to a raw (XFD) image
.\" RST source for atr2xfd(1) man page. Convert with:
@@ -198,6 +198,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/atrsize.1 b/atrsize.1
index 04b5b55..f87edce 100644
--- a/atrsize.1
+++ b/atrsize.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 "ATRSIZE" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "ATRSIZE" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
atrsize \- Change the size of an Atari 8-bit ATR disk image, or create a blank ATR image
.\" RST source for atrsize(1) man page. Convert with:
@@ -212,6 +212,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/axe.1 b/axe.1
index 4504c96..c0b658d 100644
--- a/axe.1
+++ b/axe.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 "AXE" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "AXE" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
axe \- ATR/XFD Editor
.\" RST source for axe(1) man page. Convert with:
@@ -153,6 +153,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/bas.c b/bas.c
index e90d96c..fc5517b 100644
--- a/bas.c
+++ b/bas.c
@@ -155,6 +155,10 @@ void adjust_vntable_size(int oldsize, int newsize) {
}
}
+unsigned char get_vartype(unsigned char tok) {
+ return program[vvstart + (tok & 0x7f) * 8] >> 6;
+}
+
/* return true if the variable name table is OK */
int vntable_ok(void) {
int vp, bad;
@@ -249,10 +253,109 @@ void open_output(const char *name) {
output_file = open_file(name, "wb");
}
-extern void set_self(const char *argv0) {
+void set_self(const char *argv0) {
char *p;
self = argv0;
p = strrchr(self, '/');
if(p) self = p + 1;
}
+
+/* callbacks */
+CALLBACK_PTR(on_start_line);
+CALLBACK_PTR(on_bad_line_length);
+CALLBACK_PTR(on_end_line);
+CALLBACK_PTR(on_start_stmt);
+CALLBACK_PTR(on_end_stmt);
+CALLBACK_PTR(on_cmd_token);
+CALLBACK_PTR(on_text);
+CALLBACK_PTR(on_exp_token);
+CALLBACK_PTR(on_var_token);
+CALLBACK_PTR(on_string_const);
+CALLBACK_PTR(on_num_const);
+
+#define CALL(x) if(x) (*x)(lineno, pos, program[pos], end)
+
+void walk_code(unsigned int startlineno, unsigned int endlineno) {
+ int linepos, nextpos, offset, soffset, lineno, pos, end, tok;
+
+ linepos = codestart;
+ while(linepos < filelen) { /* loop over lines */
+ lineno = getword(linepos);
+ offset = program[linepos + 2];
+ nextpos = linepos + offset;
+
+ end = nextpos;
+ pos = linepos;
+
+ if(offset < 6) {
+ CALL(on_bad_line_length);
+ offset = program[linepos + 2]; /* on_bad_line_length fixed it (we hope) */
+ if(offset < 6)
+ die("Program is code-protected; unprotect it first.");
+ }
+
+ if(lineno < startlineno) {
+ linepos = nextpos;
+ continue;
+ }
+
+ CALL(on_start_line);
+
+ pos = linepos + 3;
+ while(pos < nextpos) { /* loop over statements within a line */
+ soffset = program[pos];
+ end = linepos + soffset;
+ CALL(on_start_stmt);
+
+ while(pos < end) { /* loop over tokens within a statement */
+ pos++;
+ CALL(on_cmd_token);
+ switch(program[pos]) {
+ case CMD_REM:
+ case CMD_DATA:
+ case CMD_ERROR:
+ pos++;
+ CALL(on_text);
+ pos = end;
+ break;
+ default:
+ pos++;
+ break;
+ }
+
+ while(pos < end) { /* loop over operators */
+ tok = program[pos];
+ switch(tok) {
+ case OP_NUMCONST:
+ CALL(on_exp_token);
+ pos++;
+ CALL(on_num_const);
+ pos += 6;
+ break;
+ case OP_STRCONST:
+ CALL(on_exp_token);
+ pos++;
+ CALL(on_string_const);
+ pos += program[pos] + 1;
+ break;
+ default:
+ if(tok & 0x80) {
+ CALL(on_var_token);
+ } else {
+ CALL(on_exp_token);
+ }
+ pos++;
+ break;
+ }
+ }
+ CALL(on_end_stmt);
+ }
+ }
+
+ CALL(on_end_line);
+
+ if(lineno >= endlineno) break;
+ linepos = nextpos;
+ }
+}
diff --git a/bas.h b/bas.h
index 9d117cc..eb3f4e5 100644
--- a/bas.h
+++ b/bas.h
@@ -42,6 +42,10 @@
#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 OP_GOTO 0x17
#define OP_GOSUB 0x18
#define OP_THEN 0x1b
@@ -56,6 +60,26 @@
#define TYPE_ARRAY 1
#define TYPE_STRING 2
+/* callbacks */
+#define CALLBACK(x) void x(unsigned int lineno, unsigned int pos, unsigned int tok, unsigned int end)
+#define CALLBACK_PTR(x) void (*x)(unsigned int lineno, unsigned int pos, unsigned int tok, unsigned int end)
+#define walk_all_code() walk_code(0, 32768)
+
+void walk_code(unsigned int startlineno, unsigned int endlineno);
+unsigned char get_vartype(unsigned char tok);
+
+extern CALLBACK_PTR(on_start_line);
+extern CALLBACK_PTR(on_bad_line_length);
+extern CALLBACK_PTR(on_end_line);
+extern CALLBACK_PTR(on_start_stmt);
+extern CALLBACK_PTR(on_end_stmt);
+extern CALLBACK_PTR(on_cmd_token);
+extern CALLBACK_PTR(on_text);
+extern CALLBACK_PTR(on_exp_token);
+extern CALLBACK_PTR(on_var_token);
+extern CALLBACK_PTR(on_string_const);
+extern CALLBACK_PTR(on_num_const);
+
/* BASIC 14-byte header values */
extern unsigned short lomem;
extern unsigned short vntp;
diff --git a/blob2c.1 b/blob2c.1
index 97ef227..fefda0e 100644
--- a/blob2c.1
+++ b/blob2c.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 "BLOB2C" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "BLOB2C" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
blob2c \- Create C source and header files from a binary file
.\" RST source for blob2c(1) man page. Convert with:
@@ -133,6 +133,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/blob2xex.1 b/blob2xex.1
index 4524cd4..4a37c3b 100644
--- a/blob2xex.1
+++ b/blob2xex.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 "BLOB2XEX" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "BLOB2XEX" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
blob2xex \- Create Atari 8-bit executables from arbitrary data
.\" RST source for blob2xex(1) man page. Convert with:
@@ -224,6 +224,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/cart2xex.1 b/cart2xex.1
index adadec1..c20e98f 100644
--- a/cart2xex.1
+++ b/cart2xex.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 "CART2XEX" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "CART2XEX" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
cart2xex \- Convert an Atari 8-bit ROM cartridge image to a binary load file
.\" RST source for cart2xex(1) man page. Convert with:
@@ -243,6 +243,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/dasm2atasm.1 b/dasm2atasm.1
index e51c1f5..f37187a 100644
--- a/dasm2atasm.1
+++ b/dasm2atasm.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 "DASM2ATASM" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "DASM2ATASM" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
dasm2atasm \- Convert 6502 assembly source from dasm syntax to atasm or ca65 syntax.
.\" RST source for dasm2atasm(1) man page. Convert with:
@@ -240,6 +240,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/dumpbas.1 b/dumpbas.1
index 5735023..f2fa471 100644
--- a/dumpbas.1
+++ b/dumpbas.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 "DUMPBAS" 1 "2024-06-09" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "DUMPBAS" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
dumpbas \- Formatted hexdump for tokenized Atari 8-bit BASIC files
.SH SYNOPSIS
@@ -221,6 +221,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/dumpbas.c b/dumpbas.c
index 2888b52..d5404d2 100644
--- a/dumpbas.c
+++ b/dumpbas.c
@@ -79,6 +79,7 @@ void print_atascii(unsigned char c) {
/* REM, DATA, ERROR lines are terminated by $9B, a real EOL, not
the BASIC token. Since they're strings, print them in ASCII too. */
+/*
int handle_text_stmt(int pos) {
unsigned char c;
@@ -91,7 +92,24 @@ int handle_text_stmt(int pos) {
return pos;
}
+*/
+CALLBACK(handle_text) {
+ unsigned char c;
+
+ do {
+ c = program[pos];
+ print_atascii(c);
+ printf("%02x ", c);
+ pos++;
+ } while(c != 0x9b);
+}
+
+CALLBACK(handle_cmd) {
+ printf("!%02x ", tok);
+}
+
+/*
int handle_cmd(int pos) {
unsigned char tok = program[pos];
@@ -105,7 +123,9 @@ int handle_cmd(int pos) {
return pos + 1;
}
}
+*/
+/*
void handle_string(int pos) {
int i, len;
len = program[pos + 1];
@@ -117,7 +137,9 @@ void handle_string(int pos) {
}
putchar(' ');
}
+*/
+/*
void handle_num(int pos) {
int i;
printf("#%02x [", program[pos]);
@@ -125,8 +147,97 @@ void handle_num(int pos) {
printf("%02x%c", program[pos + 1 + i], (i == 5 ? ']' : ' '));
putchar(' ');
}
+*/
+
+CALLBACK(handle_op) {
+ switch(tok) {
+ case OP_EOS:
+ printf("%02x:", tok);
+ return;
+ case OP_NUMCONST:
+ putchar('#'); break;
+ case OP_STRCONST:
+ putchar('$'); break;
+ default: break;
+ }
+ printf("%02x ", tok);
+}
+
+CALLBACK(handle_var) {
+ printf("%02x", tok);
+ switch(get_vartype(tok)) {
+ case TYPE_ARRAY:
+ putchar('('); break;
+ case TYPE_STRING:
+ putchar('$'); break;
+ default: break;
+ }
+ putchar(' ');
+}
+
+CALLBACK(handle_string) {
+ int i, len;
+ len = program[pos];
+ printf("=%02x \"", len);
+ for(i = pos; i < pos + len; i++) {
+ unsigned char c = program[i + 1];
+ print_atascii(c);
+ printf("%02x%c", c, (i == (pos + len - 1) ? '"' : ' '));
+ }
+ putchar(' ');
+}
+
+CALLBACK(handle_num) {
+ int i;
+ putchar('[');
+ for(i = 0; i < 6; i++)
+ printf("%02x%c", program[pos + i], (i == 5 ? ']' : ' '));
+ putchar(' ');
+}
+
+CALLBACK(handle_start_line) {
+ printf("%5d @%04x (%02x %02x): ^%02x\n",
+ lineno, pos, program[pos], program[pos + 1], program[pos + 2]);
+}
+
+CALLBACK(handle_end_line) {
+ putchar('\n');
+}
+
+CALLBACK(handle_start_stmt) {
+ printf(" >%02x ", tok);
+}
+
+CALLBACK(handle_end_stmt) {
+ putchar('\n');
+}
+
+int main(int argc, char **argv) {
+ set_self(*argv);
+ parse_general_args(argc, argv, print_help);
+ parse_args(argc, argv);
+
+ readfile();
+ parse_header();
+
+ on_start_line = handle_start_line;
+ on_end_line = handle_end_line;
+ on_start_stmt = handle_start_stmt;
+ on_end_stmt = handle_end_stmt;
+ on_exp_token = handle_op;
+ on_cmd_token = handle_cmd;
+ on_num_const = handle_num;
+ on_string_const = handle_string;
+ on_text = handle_text;
+ on_var_token = handle_var;
+
+ walk_code(startlineno, endlineno);
+
+ return 0;
+}
/* sorry, this is horrid, more like assembly than C. */
+#if 0
int main(int argc, char **argv) {
int linepos, nextpos, offset, soffset, lineno, pos, end, tok;
@@ -196,3 +307,4 @@ int main(int argc, char **argv) {
return 0;
}
+#endif
diff --git a/fenders.1 b/fenders.1
index a733a31..44998ff 100644
--- a/fenders.1
+++ b/fenders.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 "FENDERS" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "FENDERS" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
fenders \- Install Fenders 3-sector loader in boot sectors of an ATR image
.\" RST source for fenders(1) man page. Convert with:
@@ -287,6 +287,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/manftr.rst b/manftr.rst
index 3f4ca62..ac50295 100644
--- a/manftr.rst
+++ b/manftr.rst
@@ -28,6 +28,7 @@ SEE ALSO
**rom2cart**\(1),
**unmac65**\(1),
**unprotbas**\(1),
+**vxrefbas**\(1),
**xexamine**\(1),
**xexcat**\(1),
**xexsplit**\(1),
diff --git a/rom2cart.1 b/rom2cart.1
index f02c593..83a3654 100644
--- a/rom2cart.1
+++ b/rom2cart.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 "ROM2CART" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "ROM2CART" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
rom2cart \- Convert a raw ROM image to an Atari800 CART image, or vice versa
.\" RST source for rom2cart(1) man page. Convert with:
@@ -256,6 +256,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/unmac65.1 b/unmac65.1
index 834e5b1..6694892 100644
--- a/unmac65.1
+++ b/unmac65.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 "UNMAC65" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "UNMAC65" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
unmac65 \- Detokenize Atari 8-bit Mac/65 SAVEd files.
.\" RST source for unmac65(1) man page. Convert with:
@@ -388,6 +388,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/unprotbas.1 b/unprotbas.1
index c464b12..9f4c8c5 100644
--- a/unprotbas.1
+++ b/unprotbas.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 "UNPROTBAS" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "UNPROTBAS" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
unprotbas \- Unprotect LIST-protected Atari 8-bit BASIC programs
.SH SYNOPSIS
@@ -355,6 +355,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/vxrefbas.1 b/vxrefbas.1
new file mode 100644
index 0000000..19d9d6f
--- /dev/null
+++ b/vxrefbas.1
@@ -0,0 +1,113 @@
+.\" Man page generated from reStructuredText.
+.
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" 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"
+.SH NAME
+vxrefbas \- Variable cross-reference for tokenized Atari 8-bit BASIC files
+.SH SYNOPSIS
+.sp
+vxrefbas \fBinput\-file\fP
+.SH DESCRIPTION
+.sp
+\fBvxrefbas\fP reads an Atari 8\-bit BASIC tokenized program and prints
+a list of variables, each with a list of line numbers where the
+variable is referenced.
+.sp
+Variables that aren\(aqt used by the program are listed as \fI(no references)\fP\&.
+.sp
+Each line number may be followed by one or more markers, which show the
+type of variable access.
+.INDENT 0.0
+.TP
+.B \fB=\fP
+The variable is assigned on this line, with \fILET\fP or "implied LET" (e.g.
+\fIA=1\fP).
+.TP
+.B \fB{\fP
+The variable is used as the control variable of a \fIFOR\fP loop on this line.
+.TP
+.B \fB}\fP
+The variable is used in a \fINEXT\fP on this line.
+.UNINDENT
+.SH OPTIONS
+.SS General Options
+.INDENT 0.0
+.TP
+.B \fB\-\-help\fP
+Print usage message and exit.
+.TP
+.B \fB\-\-version\fP
+Print version number and exit.
+.TP
+.B \fB\-v\fP
+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 EXIT STATUS
+.sp
+0 for success, 1 for failure.
+.SH COPYRIGHT
+.sp
+WTFPL. See \fI\%http://www.wtfpl.net/txt/copying/\fP for details.
+.SH AUTHOR
+.INDENT 0.0
+.IP B. 3
+Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\&.
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBa8eol\fP(1),
+\fBa8utf8\fP(1),
+\fBatr2xfd\fP(1),
+\fBatrsize\fP(1),
+\fBaxe\fP(1),
+\fBblob2c\fP(1),
+\fBblob2xex\fP(1),
+\fBcart2xex\fP(1),
+\fBdasm2atasm\fP(1),
+\fBdumpbas\fP(1),
+\fBf2toxex\fP(1),
+\fBfenders\fP(1),
+\fBprotbas\fP(1),
+\fBrenumbas\fP(1),
+\fBrom2cart\fP(1),
+\fBunmac65\fP(1),
+\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
+\fBxexamine\fP(1),
+\fBxexcat\fP(1),
+\fBxexsplit\fP(1),
+\fBxfd2atr\fP(1),
+\fBxex\fP(5),
+\fBatascii\fP(7).
+.sp
+Any good Atari 8\-bit book: \fIDe Re Atari\fP, \fIThe Atari BASIC Reference
+Manual\fP, the \fIOS Users\(aq Guide\fP, \fIMapping the Atari\fP, etc.
+.\" Generated by docutils manpage writer.
+.
diff --git a/vxrefbas.c b/vxrefbas.c
new file mode 100644
index 0000000..839b776
--- /dev/null
+++ b/vxrefbas.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "bas.h"
+
+int target_var, lastline, assign, is_for, is_next;
+int refcounts[128];
+
+void print_help(void) {
+ fprintf(stderr, "Usage: %s program.bas\n", self);
+ exit(0);
+}
+
+CALLBACK(new_line) {
+ assign = is_for = is_next = 0;
+}
+
+CALLBACK(end_line) {
+ if(lastline != lineno) return;
+ printf("%d%s%s%s ",
+ lineno,
+ assign ? "=" : "",
+ is_for ? "{": "",
+ is_next ? "}": "");
+}
+
+CALLBACK(new_command) {
+ if(program[pos + 1] == (target_var | 0x80)) {
+ if(tok == CMD_LET || tok == CMD_ILET) {
+ assign = 1;
+ } else if(tok == CMD_FOR) {
+ is_for = 1;
+ } else if(tok == CMD_NEXT) {
+ is_next = 1;
+ }
+ }
+}
+
+CALLBACK(handle_var) {
+ if(lastline == lineno) return;
+ if((tok & 0x7f) == target_var) {
+ refcounts[target_var]++;
+ lastline = lineno;
+ }
+}
+
+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);
+
+ open_input(argv[1]);
+
+ readfile();
+ parse_header();
+
+ on_var_token = handle_var;
+ on_start_line = new_line;
+ on_end_line = end_line;
+ on_cmd_token = new_command;
+
+ target_var = 0;
+ vnpos = vnstart;
+
+ 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');
+
+ if(target_var++ == 128) break;
+ }
+
+ printf(" %d variables, %d unreferenced.\n", target_var, unref);
+ return 0;
+}
diff --git a/vxrefbas.rst b/vxrefbas.rst
new file mode 100644
index 0000000..b06deb5
--- /dev/null
+++ b/vxrefbas.rst
@@ -0,0 +1,57 @@
+========
+vxrefbas
+========
+
+--------------------------------------------------------------
+Variable cross-reference for tokenized Atari 8-bit BASIC files
+--------------------------------------------------------------
+
+.. include:: manhdr.rst
+
+SYNOPSIS
+========
+
+vxrefbas **input-file**
+
+DESCRIPTION
+===========
+**vxrefbas** reads an Atari 8-bit BASIC tokenized program and prints
+a list of variables, each with a list of line numbers where the
+variable is referenced.
+
+Variables that aren't used by the program are listed as *(no references)*.
+
+Each line number may be followed by one or more markers, which show the
+type of variable access.
+
+**=**
+ The variable is assigned on this line, with *LET* or "implied LET" (e.g.
+ *A=1*).
+
+**{**
+ The variable is used as the control variable of a *FOR* loop on this line.
+
+**}**
+ The variable is used in a *NEXT* on this line.
+
+OPTIONS
+=======
+
+General Options
+---------------
+**--help**
+ Print usage message and exit.
+
+**--version**
+ Print version number and exit.
+
+**-v**
+ Verbose operation. When displaying a number in verbose mode, it will
+ be prefixed with *$* if it's in hex, or no prefix for decimal.
+
+EXIT STATUS
+===========
+
+0 for success, 1 for failure.
+
+.. include:: manftr.rst
diff --git a/xex.5 b/xex.5
index ee955ea..b67c6b4 100644
--- a/xex.5
+++ b/xex.5
@@ -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 "XEX" 5 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "XEX" 5 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
xex \- Atari 8-bit executable file format.
.\" RST source for xex(5) man page. Convert with:
@@ -315,6 +315,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/xex1to2.1 b/xex1to2.1
index aebc0be..3d66d3d 100644
--- a/xex1to2.1
+++ b/xex1to2.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 "XEX1TO2" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "XEX1TO2" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
xex1to2 \- Convert an Atari DOS 1.0 executable to a standard Atari executable
.\" RST source for xex1to2(1) man page. Convert with:
@@ -89,6 +89,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/xexamine.1 b/xexamine.1
index f26a92b..73031a8 100644
--- a/xexamine.1
+++ b/xexamine.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 "XEXAMINE" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "XEXAMINE" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
xexamine \- Show information on Atari 8-bit executables (XEX)
.\" RST source for xexamine(1) man page. Convert with:
@@ -147,6 +147,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/xexcat.1 b/xexcat.1
index e3467bc..57069fb 100644
--- a/xexcat.1
+++ b/xexcat.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 "XEXCAT" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "XEXCAT" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
xexcat \- Concatenate Atari 8-bit executables (XEX) into a single XEX file.
.\" RST source for xexcat(1) man page. Convert with:
@@ -207,6 +207,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/xexsplit.1 b/xexsplit.1
index e2d69b5..674dd22 100644
--- a/xexsplit.1
+++ b/xexsplit.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 "XEXSPLIT" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "XEXSPLIT" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
xexsplit \- Split a multi-segment Atari 8-bit executable (XEX) into multiple single-segment files.
.\" RST source for xexsplit(1) man page. Convert with:
@@ -200,6 +200,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),
diff --git a/xfd2atr.1 b/xfd2atr.1
index fdc0255..14e06ef 100644
--- a/xfd2atr.1
+++ b/xfd2atr.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 "XFD2ATR" 1 "2024-06-07" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "XFD2ATR" 1 "2024-06-13" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
xfd2atr \- Convert an Atari 8-bit XFD (raw) disk image to an ATR image.
.\" RST source for xfd2atr(1) man page. Convert with:
@@ -128,6 +128,7 @@ Watson <\fI\%urchlay@slackware.uk\fP>; Urchlay on irc.libera.chat \fI##atari\fP\
\fBrom2cart\fP(1),
\fBunmac65\fP(1),
\fBunprotbas\fP(1),
+\fBvxrefbas\fP(1),
\fBxexamine\fP(1),
\fBxexcat\fP(1),
\fBxexsplit\fP(1),