Rainbow Magazine BASIC program preflight tool
There are a lot of typing mistakes I make that are easily detectable: extra characters from fat fingers, mistyped parentheses, and even mistyped numbers. In an attempt to make typing BASIC programs from The Rainbow easier, as well as improve my ability to use Textastic with rcheck, I wrote this script. I wrote it somewhat haphazardly, adding new checks when I noticed that an error was detectable.
The basic idea is that since each line wraps at 32 characters, when I hit the end of the line in the Rainbow listing, I hit return. The script detects whether a line in the text file is a continuation of the previous line or a new line by looking for the line number. This solves the problem of finding a text editor that wraps at 32 characters.
But it also opens the possibility of doing some preflighting. If a line in the text file is not the final subline in a BASIC code line, it must be 32 characters long. If it isn’t, I mistyped something. And with my fat fingers, this is the most common typo. Most typos are discovered merely by making sure that each subline except the final one is exactly 32 characters.
There are also warnings, things that are probably a problem but might not be. These do not halt the program, and are displayed at the bottom of the results. They are not piped to a file, so they appear in the terminal if you’re piping.
For example, if the full BASIC line is longer than 249 characters, I probably mistyped something. That’s the maximum number of characters you can type on a new BASIC line on the Color Computer. It’s a warning, not an error, because it is possible to get more characters into a line, and it occasionally happens with the one-line and two-line contest winners, since they’re specifically trying to stuff as much into a line as possible. More than 255 characters is an error. I haven’t seen anything longer than that.1
It also checks the line number. If it isn’t greater than the previous line number, I mistyped something.2
And it checks for other things that I’ve noticed are detectable. If there aren’t the same number of close parentheses as open parentheses in the full BASIC line, that’s a problem.3 It looks for mistyped and missing colons, where possible.
I also have a special option for programs that are mainly just DATA statements POKEing code into memory. Such lines should only contain specific characters, the numbers 0-9 and the letters A-F, as well as the comma or space. The option --MLDATA checks all data lines and looks for characters outside of those limits. This is for programs like Rooter in the May, 1986 Rainbow, or Vicious Vic in the July 1986 Rainbow. The former uses BASIC to create a binary file for saving; the latter uses DATA statements for the title screen.
You can also use the --warnings option to suppress all output except errors and warnings.
The script ignores blank lines, which means I can hit return twice at the end of each column on a page, to make it easier to match between the page and the screen. It also ignores lines that begin with a pound symbol at the top of a file, which allows for comments at the top about where this BASIC program came from, as well as the list of checkpoints for running against rcheck.
[toggle code]
- #!/usr/bin/perl
- # facilitate typing code from The Rainbow magazine by
- # unwrapping 32-character lines to longer BASIC lines
- # and attempting to do basic error checking along the way
- # Jerry Stratton hoboes.com/coco/
- #command-line arguments
-
while ($option = shift @ARGV) {
-
if ($option =~ /^--MLDATA$/i) {
- $machineData = 1;
-
} elsif ($option =~ /^--help/i) {
- help();
-
} elsif ($option =~ /^--warnings/i) {
- $warnings = 1;
-
} else {
- $files[$#files+1] = $option;
- }
-
if ($option =~ /^--MLDATA$/i) {
- }
- @ARGV = @files;
- #loop through BASIC code
-
while (<>) {
- chomp;
- #ignore blank lines
- next if /^$/;
- #ignore top comments
- next if /^#/ && !defined($previousLineNumber);
- #if this is a new BASIC line, get the line number and the code in that line
- ($lineNumber, $lineCode) = ($1, $2) if /^([0-9]+) (.*)$/;
- #if this is a new BASIC line, handle the old one and start the new one
- #note it is possible for a 33rd character to be a number followed by a space
- #and if the number is greater than the current line number, the script will
- #incorrectly detect a new line
-
if ($lineNumber > $previousLineNumber || (!defined($previousLineNumber) && $lineNumber eq "0")) {
- print "\n" if $outputStarted;
- #errors or warnings on a full BASIC line basis
- #check that line is not too long
- #249 is the maximum that can be typed in initially;
- #but it is possible to get more into a line by editing it
- #longest so far: 255 characters
- die("\nLINE $previousLineNumber WAS $lineLength CHARACTERS LONG") if $lineLength > 255;
- #check for mismatched parentheses
- $openParenCount = () = $lineText =~ /\Q(/g;
- $closeParenCount = () = $lineText =~ /\Q)/g;
- die("\nLINE $previousLineNumber HAS MISMATCHED PARENTHESES") if $openParenCount != $closeParenCount;
- #commas, semicolons, or quotes instead of colons
- die("\nLINE $previousLineNumber mistyped colon: $lineText") if $lineText =~ /[,;'"][A-Z][A-Z0-9]?=/;
- #missing colon
- die("\nLINE $previousLineNumber missing colon: $lineText") if $lineText =~ /[0-9][A-Z][A-Z0-9]?\$?=/;
- #warnings, but not critical
- addWarning($previousLineNumber, "has more than 249 characters ($lineLength)") if $lineLength > 249;
- addWarning($previousLineNumber, "= should be -?: $lineText") if $lineText =~ /(PUT|LINE)\([^)]+\)=\(/;
- $lineLength = 0;
- $previousLineNumber = $lineNumber;
- $lineText = '';
- #is this a standalone DATA line?
-
if ($lineCode =~ /^DATA(.*)$/) {
- $inData = 1;
- $dataElements = $1;
-
} else {
- $inData = 0;
- }
-
} else {
- #has the line number gone down or stayed the same?
-
if ($lineNumber && $lineNumber <= $previousLineNumber) {
- #if the previous line was exactly 32 characters long,
- #assume this is not actually a new line number but rather the
- #continuation of the previous one
-
if ($previousLength != 32 || $lineCode =~ /^DATA /) {
- die("\nLINE $lineNumber COMES AFTER LINE $previousLineNumber: $_\n");
- }
- }
- #sublines should be 32 characters
-
if ($previousLength != 32) {
- print "\n" if $outputStarted;
- die("\nSUBLINE WAS NOT 32 CHARACTERS LONG in $previousLineNumber\n");
- }
- $dataElements = $_ if $inData;
- }
- #print the line unless looking for warnings only
-
if (!$warnings) {
- print;
- $outputStarted = 1;
- }
- $lineText .= $_;
- #these are for errors or warnings on a per-subline basis
- #no subline should be more than 32 characters long
- die("\nSUBLINE $_ LONGER THAN 32 CHARACTERS in $previousLineNumber\n") if length > 32;
- #if DATA elements are machine language codes, all characters should be hex or dec
- die("\nNON-HEX CHARACTER IN DATA SUBLINE $previousLineNumber: $_\n") if $machineData && $inData && $dataElements =~ /[^, 0-9A-F]/i;
- $previousLength = length;
- $lineLength += $previousLength;
- $lineNumber = '';
- }
- print "\n";
-
if (@warnings) {
- print STDERR "\nWARNING:\n";
-
for $warning (@warnings) {
- print STDERR "\t$warning\n";
- }
- }
-
sub help {
- print "$0 [--mldata] [--help] [--warnings] [filenames]\n";
- print "merge 32-character RAINBOW lines into BASIC program, performing rudimentary error checking.\n";
- print "\t--mldata: assume that DATA lines all contain machine code\n";
- print "\t--help: print this help\n";
- print "\t--warnings: do not print code, only print warnings and errors\n";
- exit;
- }
-
sub addWarning {
- my $lineNumber = shift;
- my $warning = shift;
- $warnings[$#warnings+1] = "LINE $lineNumber: $warning";
- }
I’ve run this script on several BASIC programs from Rainbow’s 1986 issues; if you want to add (or remove) checks, it’s easy to do so. Errors use die and warnings use addWarning. You can also switch them around if what I have as an error ought to be a warning in the programs you’re typing.
This script is easily used with rcheck. Run this script first, piping to a file, and then run rcheck on the file:
[toggle code]
- ~/bin/rainbow --MLDATA vicious.txt > VIC.BAS
- ~/bin/rcheck VIC.BAS 40 154 158 161 165 169 243 250 400 610 672 730 840 1070 1190 1350 1510 1680 1930 2200 2360 2520 2670 2769
Which since as I write this I am not yet finished typing Vicious Vic in, nets me:
checkpoint | checksum |
---|---|
40: | 189 |
154: | 85 |
158: | 172 |
161: | 98 |
165: | 188 |
169: | 128 |
END: | 187 |
I tend to type Rainbow code now a column at a time, and check the various checkpoints at the end of the column, or even at the end of a page. This script makes typing code from Rainbow a lot faster, if I can restrain the temptation to look at the screen when I know I just made a mistake.
In response to TRS-80 Color Computer Programming Tools: The TRS-80 Color Computer was a fascinating implementation of the 6809 computer chip, and was, from the Color Computer 1 through 3, possibly the longest-running of the old-school personal computers.
- May 4, 2022: Rainbow Magazine preflight tool enhanced
-
I’ve been silently updating the Rainbow preflight tool (Zip file, 3.2 KB) over the last couple of years, but I just added a feature that I thought worth talking about. I was typing in Charles Husak’s “Quest of the Dragon’s Gold” from the August 1984 Rainbow and the line numbers are all over the place. But between pages 32 and 36 the line number jumps from 2790 to 2840, which seemed excessively odd even for this particular program.
I did a search on the obvious line numbers that might exist to see if there were any GOTOs, GOSUBs, or so on, to the potentially missing section, and didn’t find any. But given how uneven the line numbers were, that wasn’t a great check. It occurred to me that I could have the
rainbow
script keep track of (a) all of the line numbers in the listing, and (b) all of the line numbers referenced in the code, and then cross reference them.This was fairly simple to do: there’s a subroutine to collect the line numbers, and a loop that provides a warning for every line number that doesn’t exist. Here’s the subroutine:
[toggle code]
-
sub collectLineReferences {
- my $lineNumber = shift;
- my $lineText = shift;
- $existingLines[$#existingLines+1] = $lineNumber;
-
while ($lineText =~ m/(GO *TO|GO *SUB|THEN) *([0-9]+)/g) {
- $lineReferences[$#lineReferences+1] = [$lineNumber, $1, $2];
- }
- }
And here are the warnings:
[toggle code]
- #verify that all line number references go to a line that exists
- %existingLines = map { $_ => 1 } @existingLines;
-
foreach $lineReference (@lineReferences) {
- ($lineNumber, $referenceType, $referencedLine) = @$lineReference;
-
if (!exists($existingLines{$referencedLine})) {
- print STDERR "\t$referenceType to non-existent line $referencedLine in $lineNumber\n";
- }
- }
-
sub collectLineReferences {
In fact, I haven’t seen a BASIC line longer than 251 characters in Rainbow, but one did get extended out to 255 characters in a correction. I’m guessing that an edit at some point caused the CoCo to lose those extra four characters because they went over a maximum of some kind.
↑If a BASIC code line happens to wrap at number and then space at the 33rd character, the script assumes that this is a continuation of the previous line. But if a line happens to be 32 characters long and then the next line number is mistyped, the script will fail to detect the too-low line number and instead concatenate the two lines.
↑If there are parentheses inside quotes and they don’t match up, the script will currently detect that as a problem. But again, I haven’t seen this in real life. Normally, even in strings there will be a close parenthesis for every open parenthesis.
↑
- The Rainbow Magazine July 1986 at Internet Archive
- Containing The Evictor, Vicious Vic, and Trench, among many other programs.
- The Rainbow Magazine May 1986 at Internet Archive
- Adventure in the sewers; and do all sorts of stuff with printers and banners. “Print graphics big and small.”
- Textastic: Alexander Blach
- This is a “powerful and fast text editor” both for iPad and Mac OS X. The iPad version has built-in SFTP support making it very useful for editing files on remote servers.
- TRS-80 Color Computer RCHECK+ in Perl
- I much prefer to use a modern keyboard and modern windows to type in programs. But Rainbow’s RCHECK+ was too useful to give up. This script will run RCHECK+ on a text file in the macOS Terminal or any Linux/Unix command line.
- Rainbow Magazine code preflight (Zip file, 3.2 KB)
- A Perl script to help detect errors in code typed from The Rainbow Magazine for TRS-80 Color Computers.
More BASIC
- Simple game menu for the Color Computer 2 with CoCoSDC
- This simple menu provides one screen for cartridges saved in the CoCoSDC’s flash ROM, and any number of screens for your favorite games for your friends to play.
- BASIC tokenization examined
- Why do old BASIC programs have strange characters in their .BAS files? Why do they look like they’re compiled code?
- Read BASIC out loud
- Reading BASIC out loud is a great tool for verifying that what you’ve typed in from an old-school magazine or book is correct.
- Convert PCBASIC code to TRS-80 Extended Color BASIC
- If you have a book of code written in PCBASIC, it usually isn’t hard to convert it to other Microsoft BASICs, such as on the TRS-80 Color Computers.
- SuperBASIC for the TRS-80 Color Computer
- Make BASIC Fun Again. Use loops, switches, and subroutines while writing Extended Color BASIC code for the Radio Shack Color Computer.
- Six more pages with the topic BASIC, and other related pages
More Color Computer
- Simple game menu for the Color Computer 2 with CoCoSDC
- This simple menu provides one screen for cartridges saved in the CoCoSDC’s flash ROM, and any number of screens for your favorite games for your friends to play.
- Rainbow Magazine preflight tool enhanced
- I’ve added several features to the Rainbow Magazine preflight tool, including a check for references to line numbers that don’t exist.
- CoCoFest! 2021
- Forty years later, I finally make it to CoCoFest!
- BASIC tokenization examined
- Why do old BASIC programs have strange characters in their .BAS files? Why do they look like they’re compiled code?
- What are the 8 bits in 8-bit computing?
- Retro computing is often called 8-bit computing. This is because the bytes that these computers use are composed of eight bits, and much of what the computer does is operating on these individual bits, not on the byte as a whole.
- 19 more pages with the topic Color Computer, and other related pages
More The Rainbow magazine
- Rainbow Magazine preflight tool enhanced
- I’ve added several features to the Rainbow Magazine preflight tool, including a check for references to line numbers that don’t exist.
- 8 (bit) Days of Christmas: Day 1 (Do You Hear What I Hear?)
- For day 1 of the 8 (bit) days of Christmas, John Mosley’s “Do You Hear What I Hear?” from the December, 1987, Rainbow Magazine. Mosley coaxes four-voice music out of the CoCo 1 and 2 using a machine-language program.
- 8 (bit) Days of Christmas: Day 10 (Up on the Rooftop)
- In the December 1986 Rainbow, J. D. German presented us with this game, involving flying and landing Santa to deliver presents!
- 8 (bit) Days of Christmas: Day 11 (O Christmas Tree)
- Day 11 of the 8 (bit) days of Christmas is the graphic accompaniment to “O Tannenbaum” from Robert T. Rogers “Holly Jolly Holidays”, from December 1984.
- 8 (bit) Days of Christmas: Day 100 (Hearth)
- Lower resolution graphics were more appropriate for animation, because you could page through up to eight screens like a flip book. This is Eugene Vasconi’s Holiday Hearth from December 1986.
- Five more pages with the topic The Rainbow magazine, and other related pages