From 9a128303b403eacac3db0351fceade7a0e7c5897 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Tue, 25 Jun 2024 18:49:54 -0400 Subject: listbas: pipe through a8eol or a8utf8; do not write ATASCII to terminal; add docs. --- listbas.1 | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ listbas.c | 83 ++++++++++++++++++++++++++++++-------- listbas.rst | 68 +++++++++++++++++++++++++++++++ 3 files changed, 267 insertions(+), 16 deletions(-) create mode 100644 listbas.1 create mode 100644 listbas.rst diff --git a/listbas.1 b/listbas.1 new file mode 100644 index 0000000..888df21 --- /dev/null +++ b/listbas.1 @@ -0,0 +1,132 @@ +.\" 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 "LISTBAS" 1 "2024-06-25" "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\-v\fP] [\fB\-i\fP] \fBinput\-file\fP +.SH DESCRIPTION +.sp +\fBlistbas\fP acts like the \fILIST\fP command in BASIC. It reads a +tokenized (SAVEd) BASIC program and prints the code in human\-readable +format. +.sp +By default, output is piped through \fBa8eol\fP(1), to convert ATASCII +characters to human\-readable sequences. Raw ATASCII and Unicode output +are also available. +.SH OPTIONS +.SS List options +.INDENT 0.0 +.TP +.B \fB\-i\fP +Include the immediate mode command (line 32768) in the output. +.TP +.B \fB\-a\fP +Output raw ATASCII; no translation to the host character set. Must be +used with redirection; \fBlistbas\fP will not write ATASCII to the terminal. +.TP +.B \fB\-u\fP +Use \fBa8utf8\fP(1) to translate ATASCII to ASCII. Requires \fBa8utf8\fP +somewhere in \fIPATH\fP\&. +.UNINDENT +.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 NOTES +.sp +\fBlistbas\fP is similar to Jindroush\(aqs \fBchkbas\fP\&. The main differences are: +.INDENT 0.0 +.IP \(bu 2 +\fBlistbas\fP only supports Atari BASIC, not Turbo BASIC or BASIC XL/XE. +.IP \(bu 2 +\fBlistbas\fP doesn\(aqt show information about the variables. Use \fBvxrefbas\fP +for that. +.IP \(bu 2 +\fBlistbas\fP will not write ATASCII data to your terminal. Instead, it uses +\fBa8eol\fP or \fBa8utf8\fP to convert the output to something human\-readable +that won\(aqt confuse the terminal. +.IP \(bu 2 +\fBlistbas\fP only includes line 32768 (the immediate mode command) if +specifically asked to do so. +.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), +\fBcxrefbas\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/listbas.c b/listbas.c index 6469009..86bb3f7 100644 --- a/listbas.c +++ b/listbas.c @@ -4,25 +4,35 @@ #include #include #include + #include +#include #include "bas.h" #include "bcdfp.h" #include "tokens.h" -int immediate = 0; +int immediate = 0, a8utf8 = 0, a8eol = 1; + +FILE *outfh; void print_help(void) { - printf("Usage: %s [-v] [-i] \n", self); + printf("Usage: %s [-v] [-i] [-a|-u] \n", self); + printf(" -v: verbose.\n"); + printf(" -i: show immediate mode command (line 32768).\n"); + printf(" -a: output raw ATASCII.\n"); + printf(" -u: output Unicode.\n"); } void parse_args(int argc, char **argv) { int opt; - while( (opt = getopt(argc, argv, "vi")) != -1) { + while( (opt = getopt(argc, argv, "viau")) != -1) { switch(opt) { case 'v': verbose = 1; break; case 'i': immediate = 1; break; + case 'a': a8utf8 = a8eol = 0; break; + case 'u': a8utf8 = 1; a8eol = 0; break; default: print_help(); exit(1); @@ -35,6 +45,11 @@ void parse_args(int argc, char **argv) { open_input(argv[optind]); } +void outchr(char c) { + putc(c, outfh); +} + +/* this should probably be moved to bcdfp.c */ double bcd2double(const unsigned char *num) { double result = 0, sign; int exp, i; @@ -60,17 +75,17 @@ double bcd2double(const unsigned char *num) { } void print_number(unsigned int pos) { - printf("%G", bcd2double(program + pos)); + fprintf(outfh, "%G", bcd2double(program + pos)); } void print_string(unsigned int pos, unsigned int len) { - putchar('"'); - while(len--) putchar(program[pos++]); - putchar('"'); + outchr('"'); + while(len--) outchr(program[pos++]); + outchr('"'); } CALLBACK(print_lineno) { - printf("%d ", lineno); + fprintf(outfh, "%d ", lineno); } CALLBACK(print_cmd) { @@ -88,9 +103,9 @@ CALLBACK(print_cmd) { } if(bad) - printf("(bad cmd token $%02x)", tok); + fprintf(outfh, "(bad cmd token $%02x)", tok); else - printf("%s ", name); + fprintf(outfh, "%s ", name); } CALLBACK(print_op) { @@ -119,9 +134,9 @@ CALLBACK(print_op) { } if(bad) - printf("(bad op token $%02x)", tok); + fprintf(outfh, "(bad op token $%02x)", tok); else - printf("%s", name); + fprintf(outfh, "%s", name); } CALLBACK(print_varname) { @@ -134,17 +149,51 @@ CALLBACK(print_varname) { } while(1) { c = program[i++]; - putchar(c & 0x7f); + outchr(c & 0x7f); if(c & 0x80) break; } } CALLBACK(print_text) { - while(program[pos] != 0x9b) putchar(program[pos++]); + while(program[pos] != 0x9b) outchr(program[pos++]); } CALLBACK(print_newline) { - putchar('\n'); + outchr(0x9b); +} + +void setup_outfh(void) { + const char *cmd; + + /* search current dir before PATH. no easy way to detect errors here, + have to wait until we call pclose(). */ + if(a8eol) { + cmd = "./a8eol -u -c 2>/dev/null || a8eol -u -c 2>/dev/null || exit 1"; + } else if(a8utf8) { + cmd = "./a8utf8 2>/dev/null || a8utf8 2>/dev/null || exit 1"; + } else { + if(isatty(fileno(stdout))) { + die("Refusing to write ATASCII data to the terminal."); + } + outfh = stdout; + return; + } + + outfh = popen(cmd, "w"); + if(!outfh) { + /* fork() or pipe() failed. does NOT detect if the command + wasn't found. */ + perror(self); + exit(1); + } +} + +void close_outfh(void) { + if(a8eol || a8utf8) { + if(pclose(outfh)) { + die("output filter failed; a8eol or a8utf8 not in current dir or $PATH."); + } + } } void list(void) { @@ -165,7 +214,9 @@ int main(int argc, char **argv) { readfile(); parse_header(); + setup_outfh(); list(); - + close_outfh(); + return 0; } diff --git a/listbas.rst b/listbas.rst new file mode 100644 index 0000000..8c672a2 --- /dev/null +++ b/listbas.rst @@ -0,0 +1,68 @@ +======= +listbas +======= + +-------------------------------------------------------- +List the source of a tokenized Atari 8-bit BASIC program +-------------------------------------------------------- + +.. include:: manhdr.rst + +SYNOPSIS +======== + +listbas [**-v**] [**-i**] **input-file** + +DESCRIPTION +=========== + +**listbas** acts like the *LIST* command in BASIC. It reads a +tokenized (SAVEd) BASIC program and prints the code in human-readable +format. + +By default, output is piped through **a8eol**\(1), to convert ATASCII +characters to human-readable sequences. Raw ATASCII and Unicode output +are also available. + +OPTIONS +======= + +List options +------------ + +**-i** + Include the immediate mode command (line 32768) in the output. + +**-a** + Output raw ATASCII; no translation to the host character set. Must be + used with redirection; **listbas** will not write ATASCII to the terminal. + +**-u** + Use **a8utf8**\(1) to translate ATASCII to ASCII. Requires **a8utf8** + somewhere in *PATH*. + +.. include:: genopts.rst + +NOTES +===== + +**listbas** is similar to Jindroush's **chkbas**. The main differences are: + +- **listbas** only supports Atari BASIC, not Turbo BASIC or BASIC XL/XE. + +- **listbas** doesn't show information about the variables. Use **vxrefbas** + for that. + +- **listbas** will not write ATASCII data to your terminal. Instead, it uses + **a8eol** or **a8utf8** to convert the output to something human-readable + that won't confuse the terminal. + +- **listbas** only includes line 32768 (the immediate mode command) if + specifically asked to do so. + +EXIT STATUS +=========== + +0 for success, 1 for failure. + +.. include:: manftr.rst -- cgit v1.2.3