aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--listbas.130
-rw-r--r--listbas.c172
-rw-r--r--listbas.rst26
-rw-r--r--turbo_tokens.c82
-rw-r--r--turbo_tokens.h5
6 files changed, 296 insertions, 23 deletions
diff --git a/Makefile b/Makefile
index b8e29c7..7d33a91 100644
--- a/Makefile
+++ b/Makefile
@@ -63,8 +63,8 @@ vxrefbas: bas.o
cxrefbas: bas.o bcdfp.o linetab.o
-listbas: listbas.c bas.o bcdfp.o tokens.o atables.o
- $(CC) $(CFLAGS) -o listbas listbas.c bas.o bcdfp.o tokens.o atables.o -lm
+listbas: listbas.c bas.o bcdfp.o tokens.o atables.o turbo_tokens.c
+ $(CC) $(CFLAGS) -o listbas listbas.c bas.o bcdfp.o tokens.o atables.o turbo_tokens.c -lm
bas.o: bas.c bas.h
diff --git a/listbas.1 b/listbas.1
index ba293f2..f8e4219 100644
--- a/listbas.1
+++ b/listbas.1
@@ -27,12 +27,12 @@ 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 "LISTBAS" 1 "2024-07-14" "0.2.1" "Urchlay's Atari 8-bit Tools"
+.TH "LISTBAS" 1 "2024-07-16" "0.2.1" "Urchlay's Atari 8-bit Tools"
.SH NAME
listbas \- List the source of a tokenized Atari 8-bit BASIC program
.SH SYNOPSIS
.sp
-listbas [\fB\-a\fP | \fB\-d\fP | \fB\-m\fP | \fB\-x\fP | \fB\-U\fP] [\fB\-b\fP] [\fB\-u\fP] [\fB\-i\fP] [\fB\-l\fP] [\fB\-n\fP | \fB\-C\fP] [\fB\-v\fP] [\fB\-c\fP \fIcolors\fP] \fBinput\-file\fP
+listbas [\fB\-a\fP | \fB\-d\fP | \fB\-m\fP | \fB\-x\fP | \fB\-U\fP] [\fB\-B\fP] [\fB\-u\fP] [\fB\-i\fP] [\fB\-l\fP] [\fB\-n\fP | \fB\-C\fP] [\fB\-v\fP] [\fB\-c\fP \fIcolors\fP] \fBinput\-file\fP
.SH DESCRIPTION
.sp
\fBlistbas\fP acts like the \fILIST\fP command in BASIC. It reads a
@@ -77,6 +77,30 @@ because you can\(aqt tell what the dots are supposed to represent.
.SS Other options
.INDENT 0.0
.TP
+.B \fB\-b\fP
+Set the BASIC the program was written in. Choices are:
+.INDENT 7.0
+.TP
+.B \fB\-ba\fP
+Program is Atari BASIC; this is the default.
+.TP
+.B \fB\-ba+\fP
+Program is OSS BASIC/A+.
+.TP
+.B \fB\-bt\fP
+Program is Turbo BASIC XL.
+.TP
+.B \fB\-bxl\fP
+Program is OSS BASIC XL.
+.TP
+.B \fB\-bxe\fP
+Program is OSS BASIC XE.
+.UNINDENT
+.sp
+If you see lots of "bad token XX" messages, or if the code just doesn\(aqt
+make any sense, you\(aqre using the wrong BASIC option. \fBwhichbas\fP(1)
+can (usually) detect the BASIC a program was written in.
+.TP
.B \fB\-i\fP
Include the immediate mode command (line 32768) in the output.
.TP
@@ -94,7 +118,7 @@ No color. Has no effect if \fB\-a\fP is in effect, since this
mode doesn\(aqt support color anyway. Disabling color does not
disable reverse video.
.TP
-.B \fB\-b\fP
+.B \fB\-B\fP
Use bold for color output. This may make it easier to read on
some terminals. Or, it may hurt your eyes...
.TP
diff --git a/listbas.c b/listbas.c
index dcd303b..bfe7615 100644
--- a/listbas.c
+++ b/listbas.c
@@ -11,7 +11,20 @@
#include "bas.h"
#include "bcdfp.h"
#include "tokens.h"
+#include "turbo_tokens.h"
+/*
+#include "aplus_tokens.h"
+#include "bxl_tokens.h"
+#include "bxe_tokens.h"
+*/
#include "atables.h"
+#include "whichbas.h"
+
+#define B_ATARI SRET_ATARI
+#define B_TURBO SRET_TURBO
+#define B_APLUS SRET_APLUS
+#define B_BXL SRET_BXL
+#define B_BXE SRET_BXE
#define COLOR_FMT "\x1b[%d;3%dm" /* 1st %d is 1 for bold, 2nd is color */
@@ -50,6 +63,11 @@
#define M_MAG 3 /* -m */
#define M_DOTS 4 /* -d */
+const char *cmd_tokens[256];
+const char *op_tokens[256];
+
+int bas_type = B_ATARI;
+
int output_mode = M_UTF8;
int bold = 0; /* 1 with -b */
@@ -99,14 +117,37 @@ void parse_color_scheme(const char *arg) {
color_varnames = parse_color(arg[7]);
}
+int get_bas_type(char *arg) {
+ if(arg[0] == 't')
+ return B_TURBO;
+
+ if(arg[0] == 'a') {
+ if(arg[1] == '+')
+ return B_APLUS;
+ else
+ return B_ATARI;
+ }
+
+ if(arg[0] == 'x') {
+ if(arg[1] == 'l')
+ return B_BXL;
+ else if(arg[1] == 'e')
+ return B_BXE;
+ }
+
+ fprintf(stderr, "%s: Invalid BASIC type for -b option: %s\n", self, arg);
+ exit(1);
+}
+
void print_help(void) {
- printf("Usage: %s [-a|-d|-m|-x|-U] [-b] [-i] [-l] [-u] [-n|-C] [-v] [-c *colors*] <inputfile>\n", self);
+ printf("Usage: %s [-a|-d|-m|-x|-U] [-B] [-i] [-l] [-u] [-n|-C] [-v] [-c *colors*] <inputfile>\n", self);
+ printf(" -b <XX>: set BASIC type. XX is: a = atari, t = turbo, xl, xe, a+.\n");
printf(" -U: output ATASCII as Unicode/UTF-8 (this is the default).\n");
printf(" -a: output raw ATASCII.\n");
printf(" -d: use dots instead of Unicode/UTF-8.\n");
printf(" -m: magazine style listing (see a8cat(1)).\n");
printf(" -x: XL international character set (UTF-8).\n");
- printf(" -b: use bold for color output.\n");
+ printf(" -B: use bold for color output.\n");
printf(" -i: show immediate mode command (line 32768).\n");
printf(" -l: don't print line numbers.\n");
printf(" -C: enable color syntax highlighting (this is the default).\n");
@@ -121,7 +162,7 @@ void parse_args(int argc, char **argv, int from_env) {
optind = 1;
- while( (opt = getopt(argc, argv, "UCviamnbdhxulc:")) != -1) {
+ while( (opt = getopt(argc, argv, "b:UCviamnBdhxulc:")) != -1) {
switch(opt) {
case 'U': output_mode = M_UTF8; break;
case 'a': output_mode = M_ATASCII; break;
@@ -130,11 +171,12 @@ void parse_args(int argc, char **argv, int from_env) {
case 'x': output_mode = M_UTF8_I; break;
case 'v': verbose = 1; break;
case 'i': immediate = 1; break;
- case 'b': bold = 1; break;
+ case 'B': bold = 1; break;
case 'u': underline = 1; break;
case 'C': color = 1; break;
case 'n': color = 0; break;
case 'l': skip_lineno = 1; break;
+ case 'b': bas_type = get_bas_type(optarg); break;
case 'c': parse_color_scheme(optarg); break;
case 'h': print_help(); exit(0);
default:
@@ -389,7 +431,7 @@ CALLBACK(print_cmd) {
if(tok == CMD_ILET) return;
if(color) color_on(color_cmd);
- if(tok > last_command || (!(name = commands[tok]))) {
+ if((!(name = cmd_tokens[tok]))) {
fprintf(outfh, "(bad cmd token $%02x) ", tok);
badtok = 1;
} else {
@@ -398,10 +440,70 @@ CALLBACK(print_cmd) {
if(color) color_off();
}
+void aplus_op_color_on(unsigned char tok) {
+}
+
+void op_color_on(unsigned char tok) {
+ if(!color) return;
+
+ if(bas_type == B_APLUS) {
+ aplus_op_color_on(tok);
+ return;
+ }
+
+ /* common ops for Atari, Turbo, BXL, BXE */
+ if(tok <= last_operator) {
+ if(tok > 0x3c)
+ color_on(color_func);
+ else if(tok == OP_UMINUS || tok == OP_UPLUS)
+ color_on(color_const); /* show leading sign in same color as the number */
+ else if((tok >= 0x17 && tok <= 0x1b) || (tok >= 0x28 && tok <= 0x2a))
+ color_on(color_cmd);
+ else
+ color_on(color_op);
+ return;
+ }
+
+ if(bas_type == B_TURBO) {
+ switch(tok) {
+ case 0x55:
+ case 0x58:
+ case 0x59: /* pseudo-func */
+ case 0x5b:
+ case 0x5c:
+ case 0x5e:
+ case 0x5f: /* pseudo-func */
+ case 0x60: /* pseudo-func */
+ case 0x63: /* pseudo-func */
+ case 0x64:
+ case 0x65:
+ case 0x6b:
+ case 0x6c: /* pseudo-func */
+ case 0x6d: /* pseudo-func */
+ color_on(color_func);
+ return;
+ case 0x5a:
+ case 0x5d:
+ case 0x61:
+ case 0x62:
+ case 0x6a:
+ color_on(color_cmd);
+ return;
+ default:
+ color_on(color_op);
+ }
+ }
+}
+
CALLBACK(print_op) {
const char *name;
switch(tok) {
+ case OP_HEXCONST:
+ if(color) color_on(color_op);
+ outchr('$');
+ if(color) color_off();
+ /* fall thru */
case OP_NUMCONST:
print_number(pos + 1);
return;
@@ -413,17 +515,9 @@ CALLBACK(print_op) {
default: break;
}
- if(color) {
- if(tok > 0x3c)
- color_on(color_func);
- else if(tok == OP_UMINUS || tok == OP_UPLUS)
- color_on(color_const); /* show leading sign in same color as the number */
- else if((tok >= 0x17 && tok <= 0x1b) || (tok >= 0x28 && tok <= 0x2a))
- color_on(color_cmd);
- else
- color_on(color_op);
- }
- if(tok > last_operator || (!(name = operators[tok]))) {
+ if(color) op_color_on(tok);
+
+ if((!(name = op_tokens[tok]))) {
fprintf(outfh, "(bad op token $%02x)", tok);
badtok = 1;
} else {
@@ -496,12 +590,58 @@ void list(void) {
walk_code(0, 32767 + immediate);
}
+void init_bas_tables() {
+ memmove(cmd_tokens, commands, (last_command + 1) * sizeof(char *));
+ memmove(op_tokens, operators, (last_operator + 1) * sizeof(char *));
+}
+
+void init_aplus_tables() {
+ die("BASIC A+ not supported yet!");
+ /*
+ memmove(cmd_tokens, aplus_commands, (last_aplus_command + 1) * sizeof(char *));
+ memmove(op_tokens, aplus_operators, (last_aplus_operator + 1) * sizeof(char *));
+ */
+}
+
+void init_turbo_tables() {
+ memmove(cmd_tokens + last_command + 1, turbo_cmds, turbo_cmd_size);
+ memmove(op_tokens + last_operator + 1, turbo_ops, turbo_ops_size);
+}
+
+void init_bxl_tables() {
+ die("BASIC XL not supported yet!");
+}
+
+void init_bxe_tables() {
+ die("BASIC XE not supported yet!");
+}
+
+void init_token_tables() {
+ if(bas_type == B_APLUS) {
+ init_aplus_tables();
+ return;
+ }
+
+ init_bas_tables();
+
+ if(bas_type == B_TURBO)
+ init_turbo_tables();
+ else if(bas_type == B_BXL)
+ init_bxl_tables();
+ else if(bas_type == B_BXE)
+ init_bxe_tables();
+}
+
int main(int argc, char **argv) {
set_self(*argv);
parse_general_args(argc, argv, print_help);
parse_env_args();
parse_args(argc, argv, 0);
+ if(bas_type != B_ATARI) allow_hex_const = 1;
+
+ init_token_tables();
+
readfile();
parse_header();
diff --git a/listbas.rst b/listbas.rst
index 63eb575..518dd5f 100644
--- a/listbas.rst
+++ b/listbas.rst
@@ -11,7 +11,7 @@ List the source of a tokenized Atari 8-bit BASIC program
SYNOPSIS
========
-listbas [**-a** | **-d** | **-m** | **-x** | **-U**] [**-b**] [**-u**] [**-i**] [**-l**] [**-n** | **-C**] [**-v**] [**-c** *colors*] **input-file**
+listbas [**-a** | **-d** | **-m** | **-x** | **-U**] [**-B**] [**-u**] [**-i**] [**-l**] [**-n** | **-C**] [**-v**] [**-c** *colors*] **input-file**
DESCRIPTION
===========
@@ -61,6 +61,28 @@ characters.
Other options
-------------
+**-b**
+ Set the BASIC the program was written in. Choices are:
+
+ **-ba**
+ Program is Atari BASIC; this is the default.
+
+ **-ba+**
+ Program is OSS BASIC/A+.
+
+ **-bt**
+ Program is Turbo BASIC XL.
+
+ **-bxl**
+ Program is OSS BASIC XL.
+
+ **-bxe**
+ Program is OSS BASIC XE.
+
+ If you see lots of "bad token XX" messages, or if the code just doesn't
+ make any sense, you're using the wrong BASIC option. **whichbas**\(1)
+ can (usually) detect the BASIC a program was written in.
+
**-i**
Include the immediate mode command (line 32768) in the output.
@@ -78,7 +100,7 @@ Other options
mode doesn't support color anyway. Disabling color does not
disable reverse video.
-**-b**
+**-B**
Use bold for color output. This may make it easier to read on
some terminals. Or, it may hurt your eyes...
diff --git a/turbo_tokens.c b/turbo_tokens.c
new file mode 100644
index 0000000..2278e21
--- /dev/null
+++ b/turbo_tokens.c
@@ -0,0 +1,82 @@
+/* these start at token 0x38 */
+const char *turbo_cmds[] = {
+ "DPOKE", /* $38 */
+ "MOVE",
+ "-MOVE",
+ "*F",
+ "REPEAT",
+ "UNTIL",
+ "WHILE",
+ "WEND",
+ "ELSE", /* $40 */
+ "ENDIF",
+ "BPUT",
+ "BGET",
+ "FILLTO",
+ "DO",
+ "LOOP",
+ "EXIT",
+ "DIR", /* $48 */
+ "LOCK",
+ "UNLOCK",
+ "RENAME",
+ "DELETE",
+ "PAUSE",
+ "TIME$=",
+ "PROC",
+ "EXEC", /* $50 */
+ "ENDPROC",
+ "FCOLOR",
+ "*L",
+ "------------------------------",
+ "RENUM",
+ "DEL",
+ "DUMP",
+ "TRACE", /* $58 */
+ "TEXT",
+ "BLOAD",
+ "BRUN",
+ "GO#",
+ "#",
+ "*B",
+ "PAINT",
+ "CLS", /* $58 */
+ "DSOUND",
+ "CIRCLE",
+ "%PUT",
+ "%GET" /* $64 */
+};
+
+const int turbo_cmd_size = sizeof(turbo_cmds);
+
+/* these start at token 0x55 */
+const char *turbo_ops[] = {
+ "DPEEK", /* $55 */
+ "&",
+ "!",
+ "INSTR", /* $58 */
+ "INKEY$",
+ " EXOR ",
+ "HEX$",
+ "DEC",
+ " DIV ",
+ "FRAC",
+ "TIME$",
+ "TIME", /* $60 */
+ " MOD ",
+ " EXEC ",
+ "RND",
+ "RAND",
+ "TRUNC",
+ "%0",
+ "%1",
+ "%2", /* $68 */
+ "%3",
+ " GO# ",
+ "UINSTR",
+ "ERR",
+ "ERL", /* $6D */
+};
+
+const int turbo_ops_size = sizeof(turbo_ops);
+
diff --git a/turbo_tokens.h b/turbo_tokens.h
new file mode 100644
index 0000000..7696d52
--- /dev/null
+++ b/turbo_tokens.h
@@ -0,0 +1,5 @@
+extern const char *turbo_cmds[] ;
+extern const int turbo_cmd_size ;
+
+extern const char *turbo_ops[] ;
+extern const int turbo_ops_size ;