From 5b4d161d5c82105f92006aa9cebbcd72b9383178 Mon Sep 17 00:00:00 2001 From: "B. Watson" 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